How To Use GraphLookup In Mongodb

Posted By Vipul Pandey | 28-Jan-2018

MongoDB has added a new feature in its version 3.4 $graphLookup, Its is an extended version of $lookup and has enhanced capabilities which are used to perform a recursive search on a collection in an array with multiple values/fields.

To understands this lets take an example ,I am going to add 5 records of employees with  the Details (Array Supervisors) which will contains the _id's of Supervisors

db.persons.insertMany([
  { _id: 11, firstName: 'Vipul', Supervisors: [13,15] },
  { _id: 12, firstName: 'Maneesh'},
  { _id: 13, firstName: 'Rijul', Supervisors: [12] },
  { _id: 14, firstName: 'Pulkit', Supervisors: [13] },
  { _id: 15, firstName: 'Anil', Supervisors: [13] }
]);
{ "acknowledged" : true, "insertedIds" : [ 11, 12, 13, 14, 15 ] }

To view All records :

db.persons.find()
{ "_id" : 11, "firstName" : "Vipul", "Supervisors" : [ 13, 15 ] }
{ "_id" : 12, "firstName" : "Maneesh" }
{ "_id" : 13, "firstName" : "Rijul", "Supervisors" : [ 12 ] }
{ "_id" : 14, "firstName" : "Pulkit", "Supervisors" : [ 13 ] }
{ "_id" : 15, "firstName" : "Anil", "Supervisors" : [ 13 ] }

Now if we want to get users with the details of the Supervisors we can use $graphLookup on Supervisors array in the following form

db.persons.aggregate( [
   {
      $graphLookup: {
         from: "persons",
         startWith: "$Supervisors",
         connectFromField: "Supervisors",
         connectToField: "_id",
         as: "supervisors"
      }
   }
])

{ "_id" : 11, "firstname" : "Vipul", "Supervisors" : [1 3, 15 ], "supervisors" : [ { "_id" : 12, "firstname" : "Maneesh" }, { "_id" :1 5, "firstname" : "Anil", "firstname" : [1 3 ] }, { "_id" : 13, "firstname" : "Rijul", "Supervisors" : [ 12 ] } ] }

{ "_id" : 12, "name" : "Maneesh", "Supervisors" : [ ] }

{ "_id" : 13, "name" : "Rijul", "Supervisors" : [ 12 ], "supervisors" : [ { "_id" : 12, "name" : "Maneesh" } ] }

{ "_id" : 14, "name" : "Pulkit", "Supervisors" : [ 13 ], "supervisors" : [ { "_id" : 12, "name" : "Maneesh" }, { "_id" : 13, "name" : "Rijul", "Supervisors" : [1 2 ] } ] }

{ "_id" : 15, "name" : "Anil", "Supervisors" : [ 13 ], "Supervisors" : [ { "_id" : 12, "name" : "Maneesh" }, { "_id" : 13, "name" : "Rijul", "Supervisors" : [ 12 ] } ] }

  1. from: specify the collection from which you need to search, It can be used in same collection or in different as well
  2. startWith: Name of Array
  3. connectFromField: field of Array
  4. connectToField: from which field It will match
  5. as: Name of array in which we need our response to get only name of managers we can use $project which will return only specific property of Supervisors array
db.users.aggregate([{ $graphLookup: {from: "users",startWith: "$Supervisors",connectFromField: "Supervisors",connectToField: "_id",as: "Supervisors"}},
                    {"$project":{"_id":1,"name":1,"Supervisors.name":1}}])
It will give us 
{ "_id" : 11, "name" : "Vipul", "Supervisors" : [ { "name" : "Maneesh" }, { "name" : "Anil" }, { "name" : "Rijul" } ] }
{ "_id" : 12, "name" : "Maneesh", "Supervisors" : [ ] }
{ "_id" : 13, "name" : "Rijul", "Supervisors" : [ { "name" : "Maneesh" } ] }
{ "_id" : 14, "name" : "Pulkit", "Supervisors" : [ { "name" : "Maneesh" }, { "name" : "Rijul" } ] }
{ "_id" : 15, "name" : "Anil", "Supervisors" : [ { "name" : "Maneesh" }, { "name" : "Rijul" } ] }

Point to Ponder 

  1. The $graphLookup stage must stay within the 100 megabyte memory limit.
  2. User Vipul has only 2 Supervisors ([13,15]) but the response is contained Name of 3 Supervisors with Rijul, Maneesh, and Anil, Its due to the fact it is searching a recursive search in the array. I will describe It in next blog how to get only Level 1 Supervisors of users, Keep reading.
Request for Proposal

Recaptcha is required.

Sending message..