MongoDB Document Operations are Atomic and Isolated, but Are They Consistent?

前端 未结 2 509
南笙
南笙 2020-12-28 17:56

I\'m in the process of porting my application from an App Engine Datastore to a MongoDB backend and have a question regarding the consistency of \"document updates.\" I und

2条回答
  •  旧巷少年郎
    2020-12-28 18:22

    There may be other ways to accomplish this, but one approach is to version your documents, and issue updates against only the version that the user had previously read (i.e., ensure that no one else has updated the document since it was last read). Here's a brief example of this technique using pymongo:

    >>> db.foo.save({'_id': 'a', 'version': 1, 'things': []}, safe=True)
    'a'
    >>> db.foo.update({'_id': 'a', 'version': 1}, {'$push': {'things': 'thing1'}, '$inc': {'version': 1}}, safe=True)
    {'updatedExisting': True, 'connectionId': 112, 'ok': 1.0, 'err': None, 'n': 1}
    

    note in the above, key "n" is 1, indicating that the document was updated

    >>> db.foo.update({'_id': 'a', 'version': 1}, {'$push': {'things': 'thing2'}, '$inc': {'version': 1}}, safe=True)
    {'updatedExisting': False, 'connectionId': 112, 'ok': 1.0, 'err': None, 'n': 0}
    

    here where we tried to update against the wrong version, key "n" is 0

    >>> db.foo.update({'_id': 'a', 'version': 2}, {'$push': {'things': 'thing2'}, '$inc': {'version': 1}}, safe=True)
    {'updatedExisting': True, 'connectionId': 112, 'ok': 1.0, 'err': None, 'n': 1}
    >>> db.foo.find_one()
    {'things': ['thing1', 'thing2'], '_id': 'a', 'version': 3}
    

    Note that this technique relies on using safe writes, otherwise we don't get an acknowledgement indicating the number of documents updated. A variation on this would use the findAndModify command, which will either return the document, or None (in Python) if no document matching the query was found. findAndModify allows you to return either the new (i.e. after updates are applied) or old version of the document.

提交回复
热议问题