原子更新或推送元素

我在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
        }
    ]
}

基于某些事件,我必须更新现有服务器的cpu和内存字段,或者在阵列中不存在新增服务器的情况下添加新的服务器。 目前,我正在分两步执行此操作。 首先检查服务器是否已经存在于阵列中。 如果是,请更新cpu和内存字段。 否则,在阵列中推入一个新的子文档。 由于应用程序的多线程性质,有时会将相同的服务器多次添加到阵列。 是否有任何原子操作符执行以下两个操作(类似于$setOnInsert运算符):

  • 如果元素存在于数组中,请更新其字段。
  • 如果数组中不存在元素,则推新元素。
  • 注意:运算符$addToSet在上述情况下不起作用,因为cpu或内存的值可能不同。


    我认为你可以使用findAndModify()来做到这一点,因为它提供了原子更新。 但是你的文档结构不合适。 如果您可以将文档更改为此(即serverID成为阵列的关键字):

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

    然后,您可以使用一个原子命令findAndModify()来更新,而无需使用两个单独的find()update()

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

    当使用这个时,如果servers.server4不存在,它将被插入,否则更新。


    MongoDb已经对单个文档进行了原子操作。 因此,就同时发送2条命令到数据库而言,您可以直接从盒子中覆盖。

    无论如何,当这两个命令矛盾时,你的问题就会出现。 IE如果你用同一个对象发送两个更新,Mongo的个人文档atmoicness不会帮助你。 所以你需要做的是管理你的应用程序的多线程,这样它就不会发送可能冲突的多个Mongo命令。

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

    上一篇: atomic update or push element

    下一篇: How to atomically update two documents in a collection in MongoDB