假设我有此文档:
docs: [
{
a: "a"
b: "b"
},
{
a: "a"
b: "b"
},
{
a: "a"
b: "b"
}
]
我需要获得此收藏集:
docs: [
{
a: "a"
b: "b"
},
{
a: "a"
b: "c"
},
{
a: "a"
b: "c"
}
]
如何定义使用$ []和跳过第一个文档并更改其他文档的arrayFilters?
db.collection("aaa").update(
{<query>},
{$set: {"docs.$[v].b": "c"}},
{arrayFilters: [{"v": {$not: 0}, "v.a": "a"}],
})
作为MongoDB版本> = 4.2
在.update()操作中接受聚合管道。您可以使用以下查询进行此操作:
查询:
db.getCollection("collectionName").update(
{<your filter part plus> , docs: { $exists: true, $ne: [] }}, // checks for `docs` not to be empty or not exists.
[
{
$set: {
docs: {
$concatArrays: [
[{ $arrayElemAt: ["$docs", 0] }],
{
$map: {
input: { $slice: ["$docs", 1, { $size: "$docs" }] },
in: { $cond: [ { $eq: [ "$$this.a", "a" ] }, { $mergeObjects: ["$$this", { b: "c" }] } , "$$this" ] } // Conditional check to return same object or updated object.
}
}
]
}
}
}
])
Test:在此处验证聚合管道:mongoplayground
Ref: aggregation-pipeline
说明: $set
是聚合的$addFields
的别名,如果存在该字段,它将重新创建该字段,或者将创建一个具有指定名称的新字段。最后,将使用新数组重新创建docs
字段。我们将一个数组作为input
传递给$map
运算符,此输入数组将大部分是整个原始docs
数组,但没有第一个元素。因此,$map
将重新创建一个新数组,该数组将与array converted first element
串联(对于$concatArrays
,两个args都应为数组,因此,我们拉出$docs
数组的第一个对象,并用[]
包装)它是docs
数组的数组。 $mergeObjects
仅将b
数组的每个对象内的docs
字段替换为{ b: "c" }
,但对象中的所有其他字段将保持不变。