NodeJS Mongodb仅获取更新的数组对象的ID列表

mbyulnm0  于 9个月前  发布在  Node.js
关注(0)|答案(1)|浏览(112)

下面是我收集的一个例子“消息”。

{[
  _id: xxx,
  shipment: {
   _id: xxx
  },
  messages: [
    { 
      _id: 123,
      origin: 'driver'
      isRead: false,
      ...
    },
    { 
      _id: 234,
      origin: 'driver'
      isRead: false,
      ...
    },
    { 
      _id: 345,
      origin: 'driver'
      isRead: true,
      ...
    },
    { 
      _id: 456,
      origin: 'dispatch'
      isRead: false,
      ...
    },
  ]
]}

字符串
我使用下面的代码更新数组对象,它工作得很好,但是这会返回整个文档和所有数组对象,我需要返回一个只包含更新过的对象的列表,这样我就可以提取它们的ID列表。

const message = await MessageModel.findOneAndUpdate(
{
  _id: messageId
},
{
  $set: {
    'messages.$[elem].isRead': true
  }
},
{
  arrayFilters: [{
    'elem.isRead': false,
    'elem.origin': 'driver'
  }],
  new: true
}
);


我需要以某种形式输出,这样我就可以获取更新后的ID,以便进一步处理:

messages: [
    { 
      _id: 123,
      origin: 'driver'
      isRead: true,
      ...
    },
    { 
      _id: 234,
      origin: 'driver'
      isRead: true,
      ...
    }
]

const ids = [123,234];


我知道它会返回整个文档,但我不知道在不进行多次查询和比较的情况下只获取更新的内容的最佳途径。
我试过使用聚合,但我是新来的,不能弄清楚。
任何帮助都非常感谢最好的路线。

thtygnil

thtygnil1#

MongoDB更新文档的工作。findOneAndUpdate根据投影和选项标志返回原始文档(整个文档)或更新后的文档(整个文档)-所以你不能只得到更新后的messages字段。
但是,如果您的目标是避免多个数据库查询,但能够找到更新的字段,那么您可以做以下事情-
1.在不使用new: true的情况下运行上述查询
1.这将返回更新之前的原始文档。这很有用,因为MongoDB仅在操作成功时才返回原始文档。
1.迭代messages字段以提取更新的字段
示例代码-

const message = await MessageModel.findOneAndUpdate(
    {
      _id: messageId,
      // Note below conditions are same as filters below
      'messages.isRead': false,
      'messages.origin': 'driver'
    },
    {
      $set: {
        'messages.$[elem].isRead': true
      }
    },
    {
      arrayFilters: [{
        'elem.isRead': false,
        'elem.origin': 'driver'
      }]
    }
);
// message will be the original document before update

const updatedIds = []
for (let i=0; i<message?.messages?.length; i++) {
    if (message.messages[i].isRead === false && message.messages[i].origin === 'driver') {
        // This means this field got update
        updatedIds.push(message.messages[i]._id);
    }
}

// return or use updatedIds

字符串

在where子句中包含isReadorigin的原因-

由于我们只想根据这些标志更新文档,并且只有在更新发生时才对文档感兴趣,因此在where子句中包含相应的过滤器是有意义的。这样,只有当messages数组中至少有一个元素满足条件时,查询才会进入下一步(更新)。

相关问题