在“更新”操作中使用聚合管道更新数组的元素

Abh*_*kar 5 arrays nested mongodb mongodb-query

设想

对于以下文档,我想更新数组中status特定消息messages的:

[{
    "_id" : ObjectId("6079bab4f297df39a44609cb"),
    "title" : "Test messages of single user",
    "messages" : [ 
        {
            "_id" : ObjectId("6079bab4f297df39a44609cc"),
            "body" : "Test 1",
            "status" : 1
        }, 
        {
            "_id" : ObjectId("6079bab4f297df39a44609cd"),
            "body" : "Test 2",
            "status" : 1
        }, 
        {
            "_id" : ObjectId("6079bcf7c041b00ec4cebb9d"),
            "body" : "Hello I'm Sam",
            "status" : 1
        }
    ]
}]
Run Code Online (Sandbox Code Playgroud)
  1. 更新操作中没有聚合管道的查询会更新单个消息中的状态

在这里运行下面的查询

db.update(
  { 
    "_id": ObjectId("6079bab4f297df39a44609cb"), 
    "messages": { $elemMatch: { _id: ObjectId("6079bcf7c041b00ec4cebb9d") } }
  }, 
  {
    $set: { "messages.$.status": 2 }
  }
)
Run Code Online (Sandbox Code Playgroud)
  1. 更新操作中使用聚合管道进行查询会更新所有消息中的状态

在这里运行下面的查询

db.update(
  { 
    "_id": ObjectId("6079bab4f297df39a44609cb"), 
    "messages": { $elemMatch: { _id: ObjectId("6079bcf7c041b00ec4cebb9d") } }
  }, 
  [
    {
      $set: { "messages.status": 2 }
    }
  ]
)
Run Code Online (Sandbox Code Playgroud)

MongoDB 版本:4.4

注意:由于某种原因,我需要使用第二个查询,但我无法更新单个消息的状态。它总是更新所有消息

问题

  1. 当我选择要更新的消息时,为什么第二个查询会更新所有消息中的状态?
  2. 如何使用聚合管道更新单个消息的状态(第二个查询)?

如果您可以分享查询链接,将会很有帮助

Tus*_*har 9

演示 - https://mongoplayground.net/p/VZHes8--O5O

使用$[]

过滤位置运算符 $[] 标识与更新操作的 arrayFilters 条件匹配的数组元素

db.collection.update(
 { "_id": ObjectId("6079bab4f297df39a44609cb") },
 { $set: { "messages.$[m].status": 2 } },
 { arrayFilters: [ { "m._id": ObjectId("6079bcf7c041b00ec4cebb9d") } ]
})
Run Code Online (Sandbox Code Playgroud)

更新

演示 - https://mongoplayground.net/p/GyBxksYKpmf

使用$map

db.collection.update({
  "_id": ObjectId("6079bab4f297df39a44609cb"),
  "messages": {
    $elemMatch: {
      _id: ObjectId("6079bcf7c041b00ec4cebb9d")
    }
  }
},
[
  {
    $set: {
      "messages": {
        $map: {
          input: "$messages",
          as: "m",
          in: {
            $cond: [
              { $eq: [ "$$m._id", ObjectId("6079bcf7c041b00ec4cebb9d") ] }, // condition
              { $mergeObjects: [ "$$m", { status: 2 } ] }, // true
              "$$m" // false
            ]
          }
        }
      }
    }
  }
])
Run Code Online (Sandbox Code Playgroud)

$条件

$mergeObjects

注意-在这种情况下这是矫枉过正的

  • 离巫术不远……但对我有用!MongoDB 在很多方面都非常出色。在其他方面不太出色。 (3认同)