首页 > 解决方案 > 使用 arrayFilters 的 mongoDB 更新不起作用

问题描述

我在 mongo 中有以下文档结构(简化):

{
  "_id":"5e30208675b5400cb0894c52",
  "locations": [
    {
      "name": "Pleasure Gardens",
      "id": 618,
      "areas": [
        {
          "name": "Koi Pond",
          "area_id": 159,
          "is_active": true,
        },
        ...other areas
      ],
      ...other locations 
    }
  ]
}

我正在尝试将区域数组中的is_active字段设置为 false,其中位置的 id 为 618,区域的 area_id 为 159。

我正在执行以下操作:

const db = await connectDb();

return await db
 .collection('test')
 .updateOne(
   {"locations.areas.area_id": 159},
   { $set: {"locations.$[l].areas.$[a].is_active": false }},
   { arrayFilters: [{ "l.id": 618 }, { "a.area_id": 159 }] }
);

但我得到:

MongoError: cannot use the part (locations of locations.$[l].areas.$[a].is_active) to traverse the element

我已经检查了其他响应,据我所知语法是正确的,而且我还在使用支持 nodejs 中的 arrayFilters 方法(“mongodb”:“^3.6.3”)的 mongodb 版本,所以为什么会这样对我这么残忍?为什么?!?!

更新

看完评论才发现虽然我安装了3.6.3版本的mongodb npm包,但是数据库本身的版本其实是3.0.14

这意味着不支持 arrayFilters 方法,我可能不得不采取两步方法来解决这个问题:

  1. 查询 mongodb 查找文档:
  1. 使用更新查询将 mongo 中的整个文档替换为存储在变量中的文档(而不仅仅是更新所需区域)

标签: node.jsmongodb

解决方案


对我来说工作正常(mongod/mongos 4.4.3 版):

mongos> db.l.find().pretty()
{
"_id" : "5e30208675b5400cb0894c52",
"locations" : [
    {
        "name" : "Pleasure Gardens",
        "id" : 618,
        "areas" : [
            {
                "name" : "Koi Pond",
                "area_id" : 159,
                "is_active" : true
            }
        ]
    }
]

}

 mongos> db.l.updateOne( {"locations.areas.area_id": 159} , { $set:{"locations.$[loc].areas.$[are].is_active":false }}, { arrayFilters: [{ "loc.id": 618 }, { "are.area_id": 159 }] }     )
// { "acknowledged" : true, "matchedCount" : 1, "modifiedCount" : 1 }

mongos> db.l.find({ "locations.areas.area_id": 159  } ,{"locations.areas.is_active":1  })
// { "_id" : "5e30208675b5400cb0894c52", "locations" : [ { "areas" : [ { "is_active" : false } ] } ] } 

推荐阅读