【问题标题】:MongoDB 5.0 how to upsert array data?MongoDB 5.0 如何更新数组数据?
【发布时间】:2022-04-10 00:33:40
【问题描述】:

我有一个这样的 mongo 文档。

{
    "_id": "a74e283a",
    "data": [
        {
            "origin": "apple",
            "edit": "fruit"
        },
        {
            "origin": "grape",
            "edit": "fruit"
        },
        {
            "origin": "melon",
            "edit": "fruit"
        }
    ]
}

我希望能够使用单个 mongo 命令插入和更新数组,而不是在 find() 中使用条件,然后根据对象的存在运行 insert() 和 update()。

如果我用这个更新数组的例子:

{
    "data": [
        {
            "origin": "apple",
            "edit": "fruit_edit"
        },
        {
            "origin": "pear",
            "edit": "fruit"
        }
    ]
}

结果必须是这样的:

{
    "_id": "a74e283a",
    "data": [
        {
            "origin": "apple",
            "edit": "fruit_edit"
        },
        {
            "origin": "grape",
            "edit": "fruit"
        },
        {
            "origin": "melon",
            "edit": "fruit"
        },
        {
            "origin": "pear",
            "edit": "friut"
        }
    ]
}

【问题讨论】:

    标签: mongodb mongodb-query


    【解决方案1】:

    您可以使用聚合管道进行更新。在聚合管道中放一个$set,使用$reduce处理upsert逻辑。

    $reduce中,把你的编辑数组作为初始值。当匹配时,只需保留累加器值,因为编辑已经在累加器中。当不匹配时,将数组条目附加到累加器。

    db.collection.update({},
    [
      {
        $set: {
          data: {
            "$reduce": {
              "input": "$data",
              "initialValue": // assign your edit data as init value
              [
                {
                  "origin": "apple",
                  "edit": "fruit_edit"
                },
                {
                  "origin": "pear",
                  "edit": "fruit"
                }
              ],
              "in": {
                "$cond": {
                  "if": {
                    $in: [
                      "$$this.origin",
                      "$$value.origin"
                    ]
                  },
                  "then": "$$value",
                  "else": {
                    "$concatArrays": [
                      "$$value",
                      [
                        "$$this"
                      ]
                    ]
                  }
                }
              }
            }
          }
        }
      }
    ])
    

    这是Mongo playground 供您参考。

    【讨论】:

      【解决方案2】:

      查询

      • 将新数据放在“ndata”上
      • 另外一个变量被定义为“ndata_origin”,只做 1 次项目
      • 这会过滤旧数据,并删除所有新数据 => old-without-new
      • concat old-without-new-newdata

      PlayMongo

      update({},
      [{"$set": 
         {"data": 
           {"$let": 
             {"vars": 
               {"ndata": 
                [{"origin": "apple", "edit": "fruit_edit"},
                 {"origin": "pear", "edit": "fruit"}]},
              "in": 
               {"$let": 
                 {"vars": {"ndata_origin": "$$ndata.origin"},
                  "in": 
                  {"$concatArrays": 
                    [{"$filter": 
                       {"input": "$data",
                        "cond": 
                        {"$not": [{"$in": ["$$this.origin", "$$ndata_origin"]}]}}},
                     "$$ndata"]}}}}}}}])
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-11-28
        • 2019-06-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-27
        • 2023-03-13
        • 2020-12-08
        相关资源
        最近更新 更多