$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" }}]);