结构或多或少;
[
{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: []}
]
我希望在children
数组不为空时将children
id替换为名称。
因此查询的结果预期为;
[ {id: 1, name: "alex" , children: ["felix", "hannah" , "sonny"]}
{id: 5, name: "sonny", children: ["vincenzo"]}
]
我做了什么来实现这一目标;
db.list.aggregate([
{$lookup: { from: "list", localField: "id", foreignField: "children", as: "children" }},
{$project: {"_id" : 0, "name" : 1, "children.name" : 1}},
])
用其父母填充儿童,这不是我想要的:)
{ "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" } ] }
我误解了什么?
答案 0 :(得分:9)
在使用$lookup
阶段之前,您应该为子数组使用$unwind
,然后为子项使用$lookup
。在$lookup
阶段之后,您需要使用$group
来获取带有名称的儿童数组,而不是 id
你可以尝试一下:
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
为什么使用$group
?
例如: 你的第一份文件
{id: 1, name: "alex" , children: [2, 4, 5]}
在$unwind
文档看起来像之后
{id: 1, name: "alex" , children: 2},
{id: 1, name: "alex" , children: 4},
{id: 1, name: "alex" , children: 5}
在$lookup
之后
{id: 1, name: "alex" , children: 2,
"childrenInfo" : [
{
"id" : 2,
"name" : "felix",
"children" : []
}
]},
//....
然后在$group
{id: 1, name: "alex" , children: ["felix", "hannah" , "sonny"]}
答案 1 :(得分:3)
使用当前的Mongo 3.4版本,您可以使用$graphLookup
。
$maxDepth
设置为0
进行非递归查找。您可能希望在查找之前添加$match
阶段以过滤没有子项的记录。
db.list.aggregate([{
$graphLookup: {
from: "list",
startWith: "$children",
connectFromField: "children",
connectToField: "id",
as: "childrens",
maxDepth: 0,
}
}, {
$project: {
"_id": 0,
"name": 1,
"childrenNames": "$childrens.name"
}
}]);