I’m trying to update a row in a mongoDB using pymongo. It seems to all work, except that it doesn’t actually update the row! Is there something I’m missing (like a flush command?). Code snippet below:
In [161]: articles = connection.journals.articles.find()
In [162]: articles[0]['_id']
Out[162]: ObjectId('4ee61fc0df04c08c5c510b51')
In [163]: articles[0]['newfield'] = 'Test'
In [164]: connection.journals.articles.update({'_id': articles[0]['_id']}, articles[0], safe=True)
Out[164]:
{u'connectionId': 62,
u'err': None,
u'n': 1,
u'ok': 1.0,
u'updatedExisting': True}
In [165]: articles = connection.journals.articles.find()
In [166]: articles[0]['_id']
Out[166]: ObjectId('4ee61fc0df04c08c5c510b51')
In [167]: articles[0]['newfield']
---------------------------------------------------------------------------
KeyError Traceback (most recent call last)
script.py in <module>()
----> 1
2
3
4
5
KeyError: 'newfield'
A PyMongo Cursor, the result of a
find()call, isn’t actually a list, it just implements__getitem__to emulate list-like access. In fact, each time you use item-access notation, it performs a new query against the database with an appropriateskip()andlimit()set in order to return the item you’re looking for. So, as you suspected in the comments, modifying the result ofarticles[0]won’t work, but making a reference to the result ofarticles[0], then modifying and using that inupdate()will work.You should also know that under certain circumstances (basically, if a modification causes the document to grow beyond the free space available “next” to it) the document might be moved on disk/in memory by MongoDB. Since you are not using
sort()in yourfind()call, you are getting results in an undefined order. When documents move, the order of results in thefind()call may change if documents have moved.