Reputation: 1355
The structure is more or less like;
[
{id: 1, name: "alex" , children: [2, 4, 5]},
{id: 2, name: "felix", children: []},
{id: 3, name: "kelly", children: []},
{id: 4, name: "hannah", children: []},
{id: 5, name: "sonny", children: [6]},
{id: 6, name: "vincenzo", children: []}
]
I want to replace children
id's with names when children
array is not empty.
So the result of the query is expected as;
[ {id: 1, name: "alex" , children: ["felix", "hannah" , "sonny"]}
{id: 5, name: "sonny", children: ["vincenzo"]}
]
What have I done to achieve this;
db.list.aggregate([
{$lookup: { from: "list", localField: "id", foreignField: "children", as: "children" }},
{$project: {"_id" : 0, "name" : 1, "children.name" : 1}},
])
filled children with its parent, which is not what I want :)
{ "name" : "alex", "parent" : [ ] }
{ "name" : "felix", "parent" : [ { "name" : "alex" } ] }
{ "name" : "kelly", "parent" : [ ] }
{ "name" : "hannah", "parent" : [ { "name" : "alex" } ] }
{ "name" : "sonny", "parent" : [ { "name" : "alex" } ] }
{ "name" : "vincenzo", "parent" : [ { "name" : "sonny" } ] }
What did I misunderstood?
Upvotes: 12
Views: 8330
Reputation: 75934
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"
}
}]);
Upvotes: 6
Reputation: 16805
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"]}
Upvotes: 12