atomic update or push element

I have following document in MongoDB.

{
    "_id" : ObjectId("521aff65e4b06121b688fabc"),
    "user" : "abc",
    "servers" : [
        {
            "name" : "server1",
            "cpu" : 4,
            "memory" : 4
        },
        {
            "name" : "server2",
            "cpu" : 6,
            "memory" : 6
        },
        {
            "name" : "server3",
            "cpu" : 8,
            "memory" : 8
        }
    ]
}

Based on certain events, I have to either update the cpu and memory fields of an existing server or add a new server to the array if it does not exist in the array. Currently, I am performing this operation in two steps. First check whether the server already exist in the array. If yes, update cpu and memory fields. Else, push a new sub-document in the array. Due to multi threading nature of the application, sometimes same server is added to the array multiple times. Is there any atomic operator to perform the following two operations (similar to $setOnInsert operator):

  • If element exists in the array, update its field.
  • If element does not exist in the array, push new element.
  • Note: Operator $addToSet is not working in the above case as the value of cpu or memory can be different.


    I think you can use findAndModify() to do this as it provides atomic update. But your document structure is not appropriate. If you can change your document to this (ie, serverID become the key of array):

    {
        "_id" : ObjectId("521aff65e4b06121b688fabc"),
        "user" : "abc",
        "servers" : {
           "server1" : {
                "cpu" : 4,
                "memory" : 4
            },
            "server2" : {
                "cpu" : 6,
                "memory" : 6
            },
            "server3" : {
                "cpu" : 8,
                "memory" : 8
            },
        }
    }
    

    Then you can use one atomic command findAndModify() to update without the need of using two separate find() and update() :

    db.collection.findAndModify
    (
     {query:
        {"_id" : ObjectId("521aff65e4b06121b688fabc")}, 
      update: 
        {$set: {"servers.server4": {"cpu":5, "memory":5 }}}, 
      new: true}
    )
    

    When using this, if servers.server4 does not exist, it will be inserted, otherwise updated.


    MongoDb already has atomic operations on individual documents. So as far as sending 2 commands to the DB at the same time goes, you're covered there out of the box.

    Your issue arises when those two commands are contradictory anyways. IE if you send 2 updates with the same object, Mongo's individual document atmoicness isn't going to help you. So what you need to do is manage your application's multi-threading such that it does not send Mongo multiple commands that may conflict.

    链接地址: http://www.djcxy.com/p/61954.html

    上一篇: 查询文档,更新它并将其返回给MongoDB

    下一篇: 原子更新或推送元素