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?
The MongoDB $lookup aggregation stage The aggregation pipeline stage $lookup makes it possible to join data from an input collection (the collection you’re running the query on) and a lookup collection (the collection you want data from), as long as both collections are on the same database.
Below is a MongoDB Aggregation cheat sheet that can come in very handy. Alright, we have learned some of the most important operations and stages for MongoDB Aggregations, feel free to ask any question in the comments section, I will be very happy to answer those.
With the introduction of $merge in version 4.2, MongoDB provides two stages, $merge and $out, for writing the results of the aggregation pipeline to a collection. The following summarizes the capabilities of the two stages:
Multiple join conditions. Correlated and uncorrelated subqueries. In MongoDB, a correlated subquery is a pipeline in a $lookup stage that references document fields from a joined collection. An uncorrelated subquery does not reference joined fields.
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"
}
}]);
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"]}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With