Search code examples
mongodbaggregation-frameworkgraphlookup

Simplifying graphLookup output in MongoDB


I have a collection "people" in the form:

{ "_id" : 1, "name" : "Grandma"}   
{ "_id" : 2, "name" : "Mum", "parentID": "1"}  
{ "_id" : 3, "name" : "Uncle", "parentID": "1"}  
{ "_id" : 4, "name" : "Kid", "parentID": "2"}  
{ "_id" : 5, "name" : "Sister", "parentID": "2"}

To get the ancestors of a certain person (let's say Kid), I can use a simple match and graphLookup as follows:

people.aggregate([  
    {$match: {_id: "3"}},  
    {$graphLookup:  
        {  
        from: "people",  
        startWith: "$parentID",  
        connectFromField: "parentID",  
        connectToField: "_id",  
        as: "ancestors"  
        }  
    }  
])

which will return

{ "_id" : 3, "name" : "Kid", "parentID": "2", "ancestors": [
    { "_id" : 1, "name" : "Grandma"},
    { "_id" : 2, "name" : "Mum", "parentID": "1"}]
}

Where I am stuck is how to refactor this output data into a single layered array, such that:

array = [  
{ "_id" : 1, "name" : "Grandma"},    
{ "_id" : 2, "name" : "Mum", "parentID": "1"},  
{ "_id" : 3, "name" : "Kid", "parentID": "2"}  
]

(array order isn't important).

Any help would be greatly appreciated!


Solution

    • Just need to change startWith from parentID to _id, this will return ancestors with current document
    • $project to show required fields
    result = people.aggregate([
      { $match: { _id: "3" } },
      {
        $graphLookup: {
          from: "collection",
          startWith: "$_id",
          connectFromField: "parentID",
          connectToField: "_id",
          as: "ancestors"
        }
      },
      {
        $project: {
          _id: 0,
          ancestors: 1
        }
      }
    ])
    

    Playground

    Access array by:

    finalResult = result[0]['ancestors']