Skip to content

Instantly share code, notes, and snippets.

@matinrco
Last active March 27, 2024 16:05
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 2 You must be signed in to fork a gist
  • Save matinrco/76d4652ad0aa7c0a846fb0e2a4ad0b94 to your computer and use it in GitHub Desktop.
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
// 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
}
}
])
@npthao1312
Copy link

Thanks, help a lot. Easier to understand than official docs.

@gregg-cbs
Copy link

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",
    },
  ]
}

@bhagwatchouhan
Copy link

bhagwatchouhan commented Jan 29, 2024

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