La estructura es más o menos como;
[ {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: []} ] Quiero reemplazar las identificaciones de los children con nombres cuando la matriz de children no está vacía.
Entonces, el resultado de la consulta se espera como;
[ {id: 1, name: "alex" , children: ["felix", "hannah" , "sonny"]} {id: 5, name: "sonny", children: ["vincenzo"]} ]¿Qué he hecho para lograr esto?
db.list.aggregate([ {$lookup: { from: "list", localField: "id", foreignField: "children", as: "children" }}, {$project: {"_id" : 0, "name" : 1, "children.name" : 1}}, ])llenó a los niños con su padre, que no es lo que quiero :)
{ "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" } ] }¿Qué entendí mal?
Antes de usar la etapa $lookup , debe usar $unwind para la matriz de niños y luego $lookup para los niños. Después de la etapa $lookup , debe usar $group para obtener una matriz de niños con nombre en lugar de identificación
Puedes probarlo:
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 ¿Por qué usó $group ?
Por ejemplo: su primer documento
{id: 1, name: "alex" , children: [2, 4, 5]} después $unwind , su documento se verá como
{id: 1, name: "alex" , children: 2}, {id: 1, name: "alex" , children: 4}, {id: 1, name: "alex" , children: 5} después $lookup
{id: 1, name: "alex" , children: 2, "childrenInfo" : [ { "id" : 2, "name" : "felix", "children" : [] } ]}, //.... luego despues $group
{id: 1, name: "alex" , children: ["felix", "hannah" , "sonny"]}Con la versión actual de Mongo 3.4, puede utilizar $graphLookup .
$maxDepth establecido en 0 para una búsqueda no recursiva. Es posible que desee agregar una etapa $match antes de la búsqueda para filtrar los registros sin elementos secundarios.
db.list.aggregate([{ $graphLookup: { from: "list", startWith: "$children", connectFromField: "children", connectToField: "id", as: "childrens", maxDepth: 0, } }, { $project: { "_id": 0, "name": 1, "childrenNames": "$childrens.name" } }]);