【问题标题】:MongoDB arrays - atomic update or push elementMongoDB 数组 - 原子更新或推送元素
【发布时间】:2016-02-25 22:43:49
【问题描述】:

我在 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操作符):

  1. 如果数组中存在元素,则更新其字段。
  2. 如果数组中不存在元素,则推送新元素。

注意:运算符$addToSet在上述情况下不起作用,因为cpu或内存的值可能不同。

【问题讨论】:

    标签: arrays mongodb


    【解决方案1】:

    MongoDb 已经有atomic operations on individual documents。因此,只要同时向数据库发送 2 个命令,您就可以立即使用。

    当这两个命令相互矛盾时,就会出现您的问题。 IE 如果您使用相同的对象发送 2 个更新,Mongo 的单个文档气氛不会帮助您。因此,您需要做的是管理应用程序的多线程,使其不会向 Mongo 发送可能发生冲突的多个命令。

    【讨论】:

    • 谢谢。我做了类似于你建议的事情。现在,应用程序确保同一服务器的两个更新由同一线程处理。
    • 如果多实例部署很常见,这并不能解决问题。
    【解决方案2】:

    我认为您可以使用 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不存在则插入,否则更新。

    【讨论】:

    • 谢谢。此模式将简化数据插入。但是,它会使获取查询复杂化。应用程序的主要要求之一是列出具有 cpu 和 memory 列的服务器。它们还支持过滤和排序(例如,列出所有 cpu > 4 的服务器)。目前,我正在使用带有 $unwind(聚合)的数组来列出服务器。
    猜你喜欢
    • 2014-07-29
    • 2014-07-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-07
    • 2012-03-04
    • 2016-01-20
    相关资源
    最近更新 更多