MongoDB在循环中更新Query

时间:2018-04-13 05:53:06

标签: mongodb

我正在我的一个项目中使用MongoDB。对于下一个特性,我需要通过循环匹配条件为对象数组添加一个标志。

以下是我的文档示例 -

{
    "_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
    "colors" : [
       { "status" : "done" },
       { "status" : "done" },
       { "status" : "n/a" }
   ]        
}

输出应为 -

{
   "_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
   "colors" : [
       {
           "status" : "done",
           "is_in_production" : true
       }, 
       {
           "status" : "done",
           "is_in_production" : true
       },
       {
        "status" : "n/a"
       }
   ]
}

我使用了以下查询 -

db.getCollection('products').update( 
   {
       "colors.status": {
          "$in":[
             "done"
          ]
       }
   },
   {$set: { 'colors.$[].is_in_production' :true }},
   {multi: true}
)

导致以下错误 -

cannot use the part(colors of colors.$[].is_in_production)totraversetheelement({ colors: [{ "status" : "done" }, { "status" : "done" }, { "status" : "n/a" }] )}

有人可以帮我查询吗?在此先感谢

2 个答案:

答案 0 :(得分:1)

使用arrayFilters仅更新嵌入文档的子集。

尝试此查询:

db.products.update(
{
   "colors.status": {
      "$in":[
         "done"
        ]
     }
  },
  {$set: { 'colors.$[element].is_in_production' :true }},
  {multi: true, arrayFilters:[{"element.status":"done"}]}
)

输出是:

/* 1 */
{
"_id" : ObjectId("5aaa4eb211a1c1c1f74c1657"),
"colors" : [ 
    {
        "status" : "done",
        "is_in_production" : true
    }, 
    {
        "status" : "done",
        "is_in_production" : true
    }, 
    {
        "status" : "n/a"
    }
  ]
}

enter image description here

请注意,您需要MongoDB 3.6,并且需要在最新的shell上执行(最好不要使用第三方工具)才能使arrayFilters正常工作。

如果上述查询不适用于您的Mongo版本,请尝试以下查询:

db.sample.findAndModify({
  query:{
     "colors.status": {
        "$in":[
           "done"
        ]
     }
 },
 update:{$set: { 'colors.$[element].is_in_production' : true }},
 multi: true, 
 arrayFilters:[{"element.status":"done"}]
})

答案 1 :(得分:1)

使用updateManyarrayFilters一起更新数组中的多个文档

db.products.updateMany(
   { "colors.status": "done" },
   { $set: { "colors.$[element].is_in_production" : true}},
   { arrayFilters: [{"element.status" : "done"}]}
)