Last active
March 27, 2024 16:05
-
-
Save matinrco/76d4652ad0aa7c0a846fb0e2a4ad0b94 to your computer and use it in GitHub Desktop.
Brief example of MongoDB graphLookup to work with tree structure such as e-commerce product categories
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// Insert some data | |
db.product_categories.insertMany([ | |
{ | |
_id: 1, | |
name: 'Products', | |
parent_id: null | |
}, | |
{ | |
_id: 2, | |
name: 'Digital & Electronics', | |
parent_id: 1 | |
}, | |
{ | |
_id: 3, | |
name: 'Clothing', | |
parent_id: 1 | |
}, | |
{ | |
_id: 4, | |
name: 'Books', | |
parent_id: 1 | |
}, | |
{ | |
_id: 5, | |
name: 'Mobile Phone', | |
parent_id: 2 | |
}, | |
{ | |
_id: 6, | |
name: 'Mobile Phone Accessories', | |
parent_id: 5 | |
}, | |
{ | |
_id: 7, | |
name: 'Mobile Phone Pouch covers', | |
parent_id: 6 | |
}, | |
{ | |
_id: 8, | |
name: 'Mobile Phone Power banks', | |
parent_id: 6 | |
} | |
]); | |
// Get specific node children | |
db.product_categories.aggregate([ | |
{ | |
$match: { | |
_id: 1 | |
} | |
}, | |
{ | |
$graphLookup: { | |
from: "product_categories", | |
startWith: "$_id", | |
connectFromField: "_id", | |
connectToField: "parent_id", | |
as: "children" | |
} | |
}, | |
{ | |
$project: { | |
'name': 1, | |
'children._id': 1, | |
'children.name': 1 | |
} | |
} | |
]) | |
// Get specific node parents | |
db.product_categories.aggregate([ | |
{ | |
$match: { | |
_id: 6 | |
} | |
}, | |
{ | |
$graphLookup: { | |
from: "product_categories", | |
startWith: "$parent_id", | |
connectFromField: "parent_id", | |
connectToField: "_id", | |
as: "parents" | |
} | |
}, | |
{ | |
$project: { | |
'name': 1, | |
'parents._id': 1, | |
'parents.name': 1 | |
} | |
} | |
]) |
From what I can see this will not give the desired nested structure that most people are looking for in $graphlookup which is:
{
"_id": {
"$oid": "641841c3ae5e0d1f81c21df4"
},
"name": "backup-power",
"slug": "backup-power",
"label": "Back-up Power",
"items": [
{
"_id": {
"$oid": "6418bf4cae5e0d1f81c21dfc"
},
"name": "inverters",
"slug": "backup-power/inverters",
"label": "Inverters",
"parent": "641841c3ae5e0d1f81c21df4",
"items": [
{
"_id": {
"$oid": "641b058aae5e0d1f81c21e0d"
},
"name": "hybrid-inverters",
"slug": "backup-power/inverters/hybrid-inverters",
"label": "Hybrid Inverters",
"parent": "6418bf4cae5e0d1f81c21dfc"
}
]
},
]
}
It will only give one level deep:
{
"_id": {
"$oid": "641841c3ae5e0d1f81c21df4"
},
"name": "backup-power",
"slug": "backup-power",
"label": "Back-up Power",
"items": [
{
"_id": {
"$oid": "6418bf4cae5e0d1f81c21dfc"
},
"name": "inverters",
"slug": "backup-power/inverters",
"label": "Inverters",
"parent": "641841c3ae5e0d1f81c21df4",
},
]
}
To get the complete list of parent child, we can set parent id in $match to null.
// Get specific node children db.product_categories.aggregate([ { $match: { parent_id: null } }, { $graphLookup: { from: "product_categories", startWith: "$_id", connectFromField: "_id", connectToField: "parent_id", as: "children" } }, { $project: { 'name': 1, 'children._id': 1, 'children.name': 1 } } ])
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Thanks, help a lot. Easier to understand than official docs.