$aggregation and $look up in the same collection- mongodb $aggregation and $look up in the same collection- mongodb mongodb mongodb

$aggregation and $look up in the same collection- mongodb


Before use $lookup stage you should use $unwind for children array then $lookup for children. After $lookup stage you need to use $group to get children array with name instead of id

You can try it:

db.list.aggregate([    {$unwind:"$children"},    {$lookup: {         from: "list",        localField: "children",        foreignField: "id",        as: "childrenInfo"       }    },    {$group:{       _id:"$_id",       children:{$addToSet:{$arrayElemAt:["$childrenInfo.name",0]}},       name:{$first:"$name"}      }    }]);// can use $push instead of $addToSet if name can be duplicate

Why used $group ?

For example:your first document

{id: 1, name: "alex" , children: [2, 4, 5]}

after $unwind your document will be look like

{id: 1, name: "alex" , children: 2},{id: 1, name: "alex" , children: 4},{id: 1, name: "alex" , children: 5}

after $lookup

{id: 1, name: "alex" , children: 2,  "childrenInfo" : [         {            "id" : 2,            "name" : "felix",            "children" : []        }    ]},//....

then after $group

 {id: 1, name: "alex" , children: ["felix", "hannah" , "sonny"]}


With the current Mongo 3.4 version you can make use of $graphLookup.

$maxDepth set at 0 for a non-recursive lookup. You may want to add a $match stage before the lookup to filter the records with no children.

db.list.aggregate([{    $graphLookup: {        from: "list",        startWith: "$children",        connectFromField: "children",        connectToField: "id",        as: "childrens",        maxDepth: 0,    }}, {    $project: {        "_id": 0,        "name": 1,        "childrenNames": "$childrens.name"    }}]);