我使用带有集合的 MongoDB 数据库,使用树父子引用。
集合中的每个文档都包含一个属性:parentId。parentId 属性是对父文档的 (ObjectId) 引用,它可以为 null。
样品:
[{
"_id": {
"$oid": "64d9f2bb7a587e250e3acb45"
},
"isActive": true,
"name": "Test1"
}, {
"_id": {
"$oid": "64dc481d37a38cb58de04ffb"
},
"isActive": true,
"name": "Test2"
}, {
"_id": {
"$oid": "64d9dd9f7a587e250e3ac95b"
},
"isActive": true,
"name": "Test1-1",
"parentId": {
"$oid": "64d9f2bb7a587e250e3acb45"
}
}, {
"_id": {
"$oid": "64dca02f0ff1ddfc4e40a874"
},
"isActive": true,
"name": "Test1-1-1",
"parentId": {
"$oid": "64d9dd9f7a587e250e3ac95b"
}
}]
我使用了
$graphLookup
,但它只获取一个列表字段中的所有子项。我需要它来填充从父级到子级的递归树结构,例如:
{
"_id": {
"$oid": "64d9f2bb7a587e250e3acb45"
},
"isActive": true,
"name": "Test1",
"childrents": [
{
"_id": {
"$oid": "64d9dd9f7a587e250e3ac95b"
},
"name": "Test1-1",
"isActive": true,
"childrents": [
{
"_id": {
"$oid": "64dca02f0ff1ddfc4e40a874"
},
"isActive": true,
"name": "Test1-1-1",
"childrents": []
}
]
}
]
}, {
"_id": {
"$oid": "64dc481d37a38cb58de04ffb"
},
"isActive": true,
"name": "Test2",
"childrents": []
}
非常感谢您的帮助,我真的很感激!
经过研究,我找到了以下解决方案https://mongoplayground.net/p/Fp5LlivVzlX。谁有更好的解决方案请告诉我。谢谢
[{
$graphLookup: {
from: 'collection',
startWith: '$_id',
connectFromField: '_id',
connectToField: 'parentId',
as: 'childrens',
restrictSearchWithMatch: {
isActive: true
},
depthField: 'level'
}
}, {
$unwind: {
path: '$childrens',
preserveNullAndEmptyArrays: true
}
}, {
$sort: {
'childrens.level': -1
}
}, {
$group: {
_id: '$_id',
parentId: {
$first: '$parentId'
},
isActive: {
$first: '$isActive'
},
name: {
$first: '$name'
},
childrens: {
$push: '$childrens'
}
}
}, {
$addFields: {
childrens: {
$reduce: {
input: '$childrens',
initialValue: {
level: -1,
presentChild: [],
prevChild: []
},
'in': {
$let: {
vars: {
prev: {
$cond: [
{
$eq: [
'$$value.level',
'$$this.level'
]
},
'$$value.prevChild',
'$$value.presentChild'
]
},
current: {
$cond: [
{
$eq: [
'$$value.level',
'$$this.level'
]
},
'$$value.presentChild',
[]
]
}
},
'in': {
level: '$$this.level',
prevChild: '$$prev',
presentChild: {
$concatArrays: [
'$$current',
[
{
$mergeObjects: [
'$$this',
{
childrens: {
$filter: {
input: '$$prev',
as: 'e',
cond: {
$eq: [
'$$e.parentId',
'$$this._id'
]
}
}
}
}
]
}
]
]
}
}
}
}
}
}
}
}, {
$addFields: {
childrens: '$childrens.presentChild'
}
}]