I use a MongoDB database with a collection, using a tree parent-children References.
Each document in the collection includes a property: parentId.The parentId property is an (ObjectId) reference to the parent document and It can be null.
Sample:
[{
"_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"
}
}]
I used $graphLookup
but It only fetch all childrens in one list field. That I need it to populate a recursive tree structure from parent to children such as:
{
"_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": []
}
Thank you so much for your help, I really appreciate it!
After researching I found a solution below https://mongoplayground.net/p/Fp5LlivVzlX. Anyone with a better solution please let me know. Thanks
[{
$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'
}
}]