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

时间:2021-04-19 13:28:10

标签: arrays mongodb nested 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
        }
    ]
}]
  1. 在更新操作中查询无聚合管道在单个消息中更新状态

在查询 here 下运行

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

在查询 here 下运行

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

MongoDB 版本:4.4

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

问题

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

如果你能分享查询链接会很有帮助

1 个答案:

答案 0 :(得分:1)

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

使用$[]

<块引用>

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

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

更新

演示 - 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
            ]
          }
        }
      }
    }
  }
])

$cond

$mergeObjects

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