gpt4 book ai didi

javascript - MongoDB - 仅在嵌套数组中存在时更新所有条目

转载 作者:行者123 更新时间:2023-12-03 07:23:42 25 4
gpt4 key购买 nike

我有一个多级嵌套文档(它是动态的,某些级别可能会丢失,但最多 3 个级别)。如果有的话,我想更新所有的 child 和子 child 路线。该场景与任何 Windows 资源管理器中的情况相同,其中所有子文件夹的路径都需要在父文件夹路径更改时更改。例如。在下面的示例中,如果我在 route=="l1/l2a" 并且它的名称需要编辑为 "l2c",那么我将更新它的路线为 route="l1/l2c 并且我将更新所有 child 的路线以说 "l1/l2c/l3a"

     {
"name":"l1",
"route": "l1",
"children":
[
{
"name": "l2a",
"route": "l1/l2a",
"children":
[
{
"name": "l3a",
"route": "l1/l2a/l3a"
}]
},
{
"name": "l2b",
"route": "l1/l2b",
"children":
[
{
"name": "l3b",
"route": "l1/l2b/l3b"
}]
}
]
}

目前我可以去一个点,我可以通过以下方式更改它的名称和路线:

router.put('/navlist',(req,res,next)=>{
newname=req.body.newName //suppose l2c
oldname=req.body.name //suppose l2a
route=req.body.route // existing route is l1/l2a
id=req.body._id


newroute=route.replace(oldname,newname); // l1/l2a has to be changed to l1/l2c
let segments = route.split('/');
let query = { route: segments[0]};
let update, options = {};

let updatePath = "";
options.arrayFilters = [];
for(let i = 0; i < segments.length -1; i++){
updatePath += `children.$[child${i}].`;
options.arrayFilters.push({ [`child${i}.route`]: segments.slice(0, i + 2).join('/') });
} //this is basically for the nested children

updateName=updatePath+'name'
updateRoute=updatePath+'route';

update = { $setOnInsert: { [updateName]:newDisplayName,[updateRoute]:newroute } };
NavItems.updateOne(query,update, options)
})

问题是我无法编辑它的子路径(如果有的话),即它的子文件夹路径为 l1/l2c/l3a。尽管我尝试如下使用 $[] 运算符。

updateChild = updatePath+'.children.$[].route'
updateChild2 = updatePath+'.children.$[].children.$[].route'
//update = { $set: { [updateChild]:'abc',[updateChild2]:'abc' } };

重要的是级别是可定制的,因此我不知道是否有“l3A”。就像可以有“l3A”但可能没有“l3B”。但是我的代码只需要每条正确的路径,否则会出错

code 500 MongoError: The path 'children.1.children' must exist in the document in order to apply array updates.

所以问题是如何使用 $set 将更改应用于实际存在的路径以及如何编辑现有路径部分。如果路径存在,那就很好,如果路径不存在,我就会收到错误。

最佳答案

更新

当您使用引用时,您可以简化更新。更新/插入很简单,因为您可以只更新目标级别或插入新级别,而不必担心更新所有级别。让聚合负责填充所有级别并生成路由字段。

工作示例 - https://mongoplayground.net/p/TKMsvpkbBMn

结构

[
{
"_id": 1,
"name": "l1",
"children": [
2,
3
]
},
{
"_id": 2,
"name": "l2a",
"children": [
4
]
},
{
"_id": 3,
"name": "l2b",
"children": [
5
]
},
{
"_id": 4,
"name": "l3a",
"children": []
},
{
"_id": 5,
"name": "l3b",
"children": []
}

]

插入查询

db.collection.insert({"_id": 4, "name": "l3a", "children": []}); // Inserting empty array simplifies aggregation query 

更新查询

db.collection.update({"_id": 4}, {"$set": "name": "l3c"});

聚合

db.collection.aggregate([
{"$match":{"_id":1}},
{"$lookup":{
"from":"collection",
"let":{"name":"$name","children":"$children"},
"pipeline":[
{"$match":{"$expr":{"$in":["$_id","$$children"]}}},
{"$addFields":{"route":{"$concat":["$$name","/","$name"]}}},
{"$lookup":{
"from":"collection",
"let":{"route":"$route","children":"$children"},
"pipeline":[
{"$match":{"$expr":{"$in":["$_id","$$children"]}}},
{"$addFields":{"route":{"$concat":["$$route","/","$name"]}}}
],
"as":"children"
}}
],
"as":"children"
}}
])

原创

在将路由呈现给用户之前,您可以将路由设置为数组类型和格式。它将大大简化您的更新。当嵌套级别不存在时(ex 级别 2 更新),您必须将查询分解为多个更新。可以使用事务以原子方式执行多个更新。

有点像

[
{
"_id": 1,
"name": "l1",
"route": "l1",
"children": [
{
"name": "l2a",
"route": [
"l1",
"l2a"
],
"children": [
{
"name": "l3a",
"route": [
"l1",
"l2a",
"l3a"
]
}
]
}
]
}
]

1 级更新

db.collection.update({
"_id": 1
},
{
"$set": {
"name": "m1",
"route": "m1"
},
"$set": {
"children.$[].route.0": "m1",
"children.$[].children.$[].route.0": "m1"
}
})

2 级更新

db.collection.update({
"_id": 1
},
{
"$set": {
"children.$[child].route.1": "m2a",
"children.$[child].name": "m2a"
}
},
{
"arrayFilters":[{"child.name": "l2a" }]
})


db.collection.update({
"_id": 1
},
{
"$set": {
"children.$[child].children.$[].route.1": "m2a"
}
},
{
"arrayFilters":[{"child.name": "l2a"}]
})

3 级更新

db.collection.update({
"_id": 1
},
{
"$set": {
"children.$[].children.$[child].name": "m3a"
"children.$[].children.$[child].route.2": "m3a"
}
},
{
"arrayFilters":[{"child.name": "l3a"}]
})

关于javascript - MongoDB - 仅在嵌套数组中存在时更新所有条目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/64732957/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com