user7725010
user7725010

Reputation: 102

Pymongo update a document with a condition

I'm trying to update a document under a condition with pymongo, but failed to figure out a way. Use this document as an example:

{"_id":"mol001",
"deid":["a001", "a003", "a005"],
"count":3}

For _id of mol001, I'm trying to append a tag to deid and update count to 4:

{"_id":"mol001",
"deid":["a001", "a003", "a005", "b001"],
"count":4}

One thing needs to be aware of is the count value. if It's larger than 10, the document will not be updated. Below is what I came up with:

    mol = "mol001"
    b001 = "b001"
    try: 
        ## in case mol001 doesn't exist, use upset = True
        count = coll.find_one({"_id": mol}, {"_id": False, "count": 1})['count']
    except:
        count = 0
    if count <= 10:
        coll.update_one({"_id": mol}, {'$push': {'deid': b001}}, upsert=True)
        coll.update_one({"_id": mol}, {"$inc": {"count": 1}}, upsert=True)

This was very inefficient since it needs to do one query and update twice. Is there a way to use $cond to do the update in one sentence?

Upvotes: 1

Views: 573

Answers (2)

rickhg12hs
rickhg12hs

Reputation: 11902

Here's one way to do it.

db.collection.update({
  "_id": "mol001",
  "count": {
    "$lte": 10
  }
},
{
  "$push": {
    "deid": "b001"
  },
  "$inc": {
    "count": 1
  }
},
{
  "upsert": true
})

Try it on mongoplayground.net.

Upvotes: 1

Belly Buster
Belly Buster

Reputation: 8814

You can combine the two operations into a single update operation:

coll.update_one({'_id': mol}, {'$push': {'deid': b001}, '$inc': {'count': 1}}, upsert=True)

Upvotes: 1

Related Questions