Mongo 当多个嵌套对象的 ID 存在于列表中时更新它们
Mongo update multiple nested objects when their ID exists in a list
当列表中存在 ID 时,我正在尝试更新嵌套数组中的许多对象。
文档结构如下:
{
id: p00,
children: [{
id: c00,
value: true
},
{
id: c01,
value: true
},
{
id: c02,
value: true
}
]
}
如果 id=p00
和 children.id
在 [c00, c01]
中,我想设置 value=false
。
这是我的尝试,但它显然正在更新,仅对父记录进行 1 次更新,这意味着只有 c00
会被修改为 false 值。
collection
.updateMany(and(
eq("id", "p00"),
in("children._id", [c00, c01])),
combine(
set("children.$.value", false)
));
这可能吗,还是我需要将子项向上移动以形成更扁平的结构?我不想这样做,因为这会引入它自己的问题。
谢谢!
您可以通过管道更新来完成。
管道更新允许我们使用所有聚合运算符,因此我们可以进行复杂的更新(在您的情况下,也许也可以使用更新运算符,但使用管道很容易)
管道更新需要 >= MongoDB 4.2.
查询
- 匹配
id=p00
- 映射子数组的每个成员(
$$c
变量)
如果 $$c.id
在列表 ["c00","c01"]
中
然后成员将 $$c
与 {"value" : false}
合并(就像添加键值对)
否则不要改变 $$c
db.collection.update({
"id": {
"$eq": "p00"
}
},
[
{
"$set": {
"children": {
"$map": {
"input": "$children",
"as": "c",
"in": {
"$cond": [
{
"$in": [
"$$c.id",
[
"c00",
"c01"
]
]
},
{
"$mergeObjects": [
"$$c",
{
"value": false
}
]
},
"$$c"
]
}
}
}
}
}
])
如果您不想使用更新管道(您的更新很简单,也可以使用数组过滤器来完成),并且在 Java 中会像下面这样。
coll.updateOne(new Document().append("id","p00"),
new Document().append("$set",new Document().append("children.$[item].value",false)),
new UpdateOptions().arrayFilters(
Collections.singletonList( Filters.in("item.id",Arrays.asList("c00","c01")))))
当列表中存在 ID 时,我正在尝试更新嵌套数组中的许多对象。
文档结构如下:
{
id: p00,
children: [{
id: c00,
value: true
},
{
id: c01,
value: true
},
{
id: c02,
value: true
}
]
}
如果 id=p00
和 children.id
在 [c00, c01]
中,我想设置 value=false
。
这是我的尝试,但它显然正在更新,仅对父记录进行 1 次更新,这意味着只有 c00
会被修改为 false 值。
collection
.updateMany(and(
eq("id", "p00"),
in("children._id", [c00, c01])),
combine(
set("children.$.value", false)
));
这可能吗,还是我需要将子项向上移动以形成更扁平的结构?我不想这样做,因为这会引入它自己的问题。
谢谢!
您可以通过管道更新来完成。
管道更新允许我们使用所有聚合运算符,因此我们可以进行复杂的更新(在您的情况下,也许也可以使用更新运算符,但使用管道很容易)
管道更新需要 >= MongoDB 4.2.
查询
- 匹配
id=p00
- 映射子数组的每个成员(
$$c
变量)
如果$$c.id
在列表["c00","c01"]
中 然后成员将$$c
与{"value" : false}
合并(就像添加键值对)
否则不要改变$$c
db.collection.update({
"id": {
"$eq": "p00"
}
},
[
{
"$set": {
"children": {
"$map": {
"input": "$children",
"as": "c",
"in": {
"$cond": [
{
"$in": [
"$$c.id",
[
"c00",
"c01"
]
]
},
{
"$mergeObjects": [
"$$c",
{
"value": false
}
]
},
"$$c"
]
}
}
}
}
}
])
如果您不想使用更新管道(您的更新很简单,也可以使用数组过滤器来完成),并且在 Java 中会像下面这样。
coll.updateOne(new Document().append("id","p00"),
new Document().append("$set",new Document().append("children.$[item].value",false)),
new UpdateOptions().arrayFilters(
Collections.singletonList( Filters.in("item.id",Arrays.asList("c00","c01")))))