【问题标题】:mongoDB update with arrayFilters not working使用 arrayFilters 的 mongoDB 更新不起作用
【发布时间】:2021-07-17 17:15:36
【问题描述】:

我在 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 版本,所以为什么对我这么残忍?为什么?!?!

更新

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

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

  1. 查询 mongodb 查找文档:
  • 将结果存储在变量中
  • 使用(将 is_active 更改为 false)更新代码本身中的变量
  1. 使用更新查询将 mongo 中的整个文档替换为存储在变量中的文档(而不仅仅是更新所需区域)

【问题讨论】:

  • 您确定您在正确的数据库中吗?
  • 你可以尝试更改命令吗? .updateOne( {"locations.areas.area_id": 159}, { $set: {"locations.$[l].areas.$.is_active": false }}, { arrayFilters: [{ "l.id": 618 }] });
  • 也许提供以下详细信息,以便我们确认正确的版本:db.version(); db.adminCommand( { getParameter: 1, featureCompatibilityVersion: 1 } );
  • @ŠtěpánZechner 在 mongodb 3.6.3、nodeJS 本机驱动器上进行了测试,并且可以正常工作(更新文档)。如果在错误的数据库中也没有错误。所以它可能是别的东西。也许代码本身......
  • 嗯..我会检查另一种方法。我认为您应该在应用程序端执行此操作,使用 {"locations.areas.area_id": 159} 带来元素并运行 for 循环。然后更新那些,这肯定是有风险的,但看不到任何替代方案。

标签: node.js mongodb


【解决方案1】:

对我来说工作正常(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 } ] } ] } 

【讨论】:

  • 伙伴这并不能解决问题,或者我可能遗漏了一些东西
  • @Minsky:成功的测试细节很难作为评论发布,所以作为答案发布......(只是试图帮助陷入困境的人......)
猜你喜欢
  • 1970-01-01
  • 2018-04-23
  • 2020-07-09
  • 2023-02-08
  • 2016-09-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多