pg2455
pg2455

Reputation: 5148

update mongodb on fly

I have a mongodb database which stores values like this:

{'_id':1, "summary":{"tags": {"Good":1, "bad": 4}}}

I want to make it such that I can enter any new tag and update the count of existing tags.

so like:

db = pymongo.MongoClient().collection.summary
tags = ['Good', 'Enjoy']
id_tags =db.find_one({'_id':1})[summary][tags].keys()
for i in tags:
    if i in id_tags:
       db.update('_id':1, {"$inc":{'summary.tags.{}'.format(i):1})
    else:
       db.update('_id':1,{"$set":{'summary.tags.{}'.format(i):1}})

Is there a way that I can do this dynamically in just one mongodb command? i.e. I do not have to deal with if else conditions? Ideally I actually want to get rid of for statement here as I am also updating other stuff in mongodb and no loop is needed for those.

Upvotes: 1

Views: 187

Answers (1)

chridam
chridam

Reputation: 103365

From the docs, the $inc operator increments a field by a specified value and has the following form:

{ $inc: { <field1>: <amount1>, <field2>: <amount2>, ... } }

If the field does not exist, $inc creates the field and sets the field to the specified value. Thus in your case the for loop becomes unnecessary as you just need one atomic update with the $inc operator set on multiple fields:

db = pymongo.MongoClient().collection.summary
db.update_one({'_id': 1}, 
    { 
        '$inc': {
            'summary.tags.Good' : 1,
            'summary.tags.Enjoy': 1
        }
    })

-- UPDATE --

To update the keys dynamically, you need to first create a dictionary that holds the keys and the incremental values:

tags = ['Good', 'Enjoy']
tags_dict = {}
for tag in tags:
    tags_dict['summary.tags.'+tag] = 1
db = pymongo.MongoClient().collection.summary
db.update_one({'_id': 1}, {'$inc': tags_dict })

Upvotes: 3

Related Questions