How to update values using pymongo?

Question:

I’ve a mongodb collection in this form:

{id=ObjectId(....),key={dictionary of values}}
where dictionary of values is {'a':'1','b':'2'.....}

Let dictionary of values be 'd'.
I need to update the values of the key in the 'd'.
i.e I want to change 'a':'1' to 'a':'2'
How can do I this in pymongo?

Code goes something like this:

productData is a collection in mongoDB
for p in productData.find():
     for k,v in p.iteritems():
         value=v['a']
         value=value+1
         v['a']=value

Now reflect the new value in the productData.

This is what I’ve tried and it introduces a new key-value pair instead of updating the

for p in productData.find():
    for k,v in p.iteritems():
         value=v['a']
         value=value+1
         v['a']=value
         productData.update({'_id':mongoId},{"$set":{'d.a':'100'}},upsert=False)
Asked By: gizgok

||

Answers:

You can use the $set syntax if you want to set the value of a document to an arbitrary value. This will either update the value if the attribute already exists on the document or create it if it doesn’t. If you need to set a single value in a dictionary like you describe, you can use the dot notation to access child values.

If p is the object retrieved:

existing = p['d']['a']

For pymongo versions < 3.0

db.ProductData.update({
  '_id': p['_id']
},{
  '$set': {
    'd.a': existing + 1
  }
}, upsert=False, multi=False)

For pymongo versions >= 3.0

db.ProductData.update_one({
  '_id': p['_id']
},{
  '$set': {
    'd.a': existing + 1
  }
}, upsert=False)

However if you just need to increment the value, this approach could introduce issues when multiple requests could be running concurrently. Instead you should use the $inc syntax:

For pymongo versions < 3.0:

db.ProductData.update({
  '_id': p['_id']
},{
  '$inc': {
    'd.a': 1
  }
}, upsert=False, multi=False)

For pymongo versions >= 3.0:

db.ProductData.update_one({
  '_id': p['_id']
},{
  '$inc': {
    'd.a': 1
  }
}, upsert=False)

This ensures your increments will always happen.

Answered By: Mark Unsworth

With my pymongo version: 3.2.2 I had do the following

from bson.objectid import ObjectId
import pymongo

client = pymongo.MongoClient("localhost", 27017)
db = client.mydbname

db.ProductData.update_one({
  '_id': ObjectId(p['_id']['$oid'])
},{
  '$set': {
    'd.a': existing + 1
  }
}, upsert=False)
Answered By: Raptor

In Python, the operators (e.g., $set) should be in quotes:

db.ProductData.update(
    {'fromAddress': 'http://localhost:7000/'},
    {'$set': {'fromAddress': 'http://localhost:5000/'}},
    {'multi': True}
)
Answered By: Adarsh R

Something I did recently, hope it helps. I have a list of dictionaries and wanted to add a value to some existing documents.

for item in my_list:
    my_collection.update({"_id" : item[key] }, {"$set" : {"New_col_name" :item[value]}})
Answered By: Jack
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.