同一集合中的$aggregation和$look-up-mongodb
结构或多或少是相似的同一集合中的$aggregation和$look-up-mongodb,mongodb,aggregation-framework,lookup,Mongodb,Aggregation Framework,Lookup,结构或多或少是相似的 [ {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, nam
[
{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}},
])
用其父对象填充子对象,这不是我想要的:)
我误解了什么?在使用
$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"]}
在当前的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"
}
}]);
谢谢你的回答。我理解我关于
localField
和foreignField
的错误。但是你能解释一下查询中的$group
吗?因为$unwind
子数组需要使用$group
来为每个子数组创建单独的文档,然后再次使用子数组来创建子数组。可以看到,在每个聚合方法之后都显示了当前状态,这使得后续操作更加容易+1.
db.list.aggregate([{
$graphLookup: {
from: "list",
startWith: "$children",
connectFromField: "children",
connectToField: "id",
as: "childrens",
maxDepth: 0,
}
}, {
$project: {
"_id": 0,
"name": 1,
"childrenNames": "$childrens.name"
}
}]);