【问题标题】:MongoDB updating the wrong subdocument in arrayMongoDB 更新数组中错误的子文档
【发布时间】:2020-10-02 09:59:47
【问题描述】:

我最近开始使用 Mongoose(来自 NodeJS)使用 MongoDB,但现在我在更新数组中的子文档时遇到了困难。 让我告诉你...

我已经像这样在 MongoDB 中设置了我的餐厅:

_id: ObjectId("5edaaed8d8609c2c47fd6582")
name: "Some name"
tables: Array
  0: Object
    id: ObjectId("5ee277bab0df345e54614b60")
    status: "AVAILABLE"
  1: Object
    id: ObjectId("5ee277bab0df345e54614b61")
    status: "AVAILABLE"

如您所见,一家餐厅显然可以有多张桌子。 现在我想更新我知道_id 的表的状态。我也知道有桌子的餐厅的_id。 但是....如果我们有相应的 tableId 并且该表的状态为“可用”,我只想更新状态。

我的更新声明:

const result = await Restaurant.updateOne(
  {
    _id: ObjectId("5edaaed8d8609c2c47fd6582"), 
    'tables._id': ObjectId("5ee277bab0df345e54614b61"), 
    'tables.status': 'AVAILABLE' 
  },
  { $set: { 'tables.$.status': 'CONFIRMED' } }
);

猜猜当我运行上面的更新语句时会发生什么? 它奇怪地更新了 FIRST 表(使用错误的 table._id)! 但是,当我从查询中删除“tables.status”过滤器时,它确实会更新正确的表:

const result = await Restaurant.updateOne(
  {
    _id: ObjectId("5edaaed8d8609c2c47fd6582"), 
    'tables._id': ObjectId("5ee277bab0df345e54614b61")
  },
  { $set: { 'tables.$.status': 'CONFIRMED' } }
);

这里的问题是我需要状态为“可用”,否则它不应该更新! 谁能指出我正确的方向?

【问题讨论】:

    标签: mongodb mongoose mongodb-query mongoose-schema


    【解决方案1】:

    根据文档,positional $ operator 充当与查询文档匹配的第一个元素的占位符

    所以您只更新文档中与您的查询匹配的第一个数组元素

    你应该使用filtered positional operator $[identifier]

    所以你的查询会是这样的

    const result = await Restaurant.updateOne(
      {
        _id: ObjectId("5edaaed8d8609c2c47fd6582"),
        'tables._id': ObjectId("5ee277bab0df345e54614b61"),
        'tables.status': 'AVAILABLE'
      },
      {
        $set: { 'tables.$[table].status': 'CONFIRMED' } // update part
      },
      { 
        arrayFilters: [{ "table._id": ObjectId("5ee277bab0df345e54614b61"), 'table.status': 'AVAILABLE' }] // options part
      }
    );
    

    通过这种方式,您正在更新具有 tableIdstatus 的表格元素

    希望对你有帮助

    【讨论】:

    • 对不起,我的回答有问题,我已经更新了我的回答,你现在可以检查一下吗?
    • "所以您只更新文档中与您的查询匹配的第一个数组元素" 嗯...这实际上是我想要实现的,但它似乎不正确。我的查询现在包含 2 个部分(tableId 和状态),但它不是在寻找这两个部分的组合......
    • 我的问题是......为什么它匹配第一个数组元素?
    • 如果tables数组有以下元素[{_id: 'tableId1, status: 'Available'}, {_id: 'tableId2, status: 'Available'}],如果只是做find查询(不更新),查询中会返回所有数组元素,如mongoDB,搜索是在文档级别完成的,而不是在数组级别,因此整个数组将在文档中返回,然后如果您要更新具有_id: 'tableId2' 的表,并且您正在使用$ operator,您将错误地将具有_id='tableId1' 的表元素更新为$ updates 数组中的第一个元素
    • 这就是为什么我们需要使用 arrayFilters 部分来更新数组中符合我们需求的元素
    猜你喜欢
    • 2015-03-30
    • 2016-12-31
    • 1970-01-01
    • 1970-01-01
    • 2017-08-22
    • 2012-11-26
    • 1970-01-01
    • 2016-11-23
    • 2016-11-04
    相关资源
    最近更新 更多