Gou*_*pil 5 graph mongodb node.js
在 MongoDB/NodeJS 项目中,我已经对集合的元素进行了排序,就像家谱一样。在特定路线中,我试图获取元素的父元素,以及父元素的兄弟元素,具有给定的深度,如下图所示:
在集合中,对于每个项目,我存储其他数据:
我试图用GraphLookup做一些事情,基于我的请求链接parentId到grandParentId,像这样:
db.arguments.aggregate([
{$match: { _id: mongoose.Types.ObjectId(id) }},
,
{$graphLookup: {
from: 'arguments',
startWith: '$grandParentId',
connectFromField: 'grandParentId',
connectToField: 'parentId',
maxDepth: Number(parentsDepth),
as: 'parentsHierarchy',
depthField: 'depth',
restrictSearchWithMatch: { isDeleted: false }
}}
])
Run Code Online (Sandbox Code Playgroud)
它工作得很好,但问题是它无法检索没有parentId. 我已经考虑过做两个单独的视图,每个视图都包含一个 a GraphLookup(一个基于parentId/ grandParentId,另一个基于id/ parentId),然后在删除重复项的同时合并两个视图,但是为了获得根而执行两个潜在的大请求看起来很奇怪元素。
我想找到一个可靠的解决方案,因为我计划允许一个项目有多个父项。
您可以将其更改为多个步骤:
db.arguments.aggregate([
{$match: { _id: mongoose.Types.ObjectId(id) }},
{$graphLookup: {
from: 'arguments',
startWith: '$parentId',
connectFromField: 'parentId',
connectToField: '_id',
maxDepth: Number(parentsDepth),
as: 'parentsHierarchy',
depthField: 'depth',
restrictSearchWithMatch: { isDeleted: false }
}},
{$unwind: "$parentsHierarchy"},
{$lookup: {
from: 'arguments',
let: { id: '$parentsHierarchy._id', depth: '$parentsHierarchy.depth' },
pipeline: [
{$match:{$expr:{
$and: [{
$eq: ['$$id', '$parentId']
},{
$gte: ["$$depth", 2]
}]
}}},
{$addFields:{
depth: {$sum: ["$$depth", -1]}
}}],
as: 'children'
}},
{$group:{
_id: "$_id",
parentsHierarchy: {$addToSet: "$parentsHierarchy"},
children: {$push: "$children"}
// The rest of your root fields will have to be added here (someField: {$first: "$someField"})
}},
{$addFields:{
hierarchy: {$setUnion: ["$children", "$parentsHierarchy"]}
}}
])
Run Code Online (Sandbox Code Playgroud)
有关 .请参阅如何在组内推送多个列的值$setUnion。
原答案:
如果您只对父级和父级的兄弟姐妹感兴趣,则可以使用 stage$lookup而不是$graphLookup,因为您不需要图表提供的递归。
你$lookup可以这样做:
db.test.aggregate([
{$lookup: {
from: 'arguments',
let: { parentId: '$parentId', grandParentId: '$grandParentId' },
pipeline: [{$match:{$expr:{
$or: [{
$eq: ['$_id', '$$parentId']
},{
$eq: [{$ifNull: ['$parentId', 'xyz']}, '$$grandParentId']
}]
}}}],
as: 'parentsAndTheirSiblings'
}}
])
Run Code Online (Sandbox Code Playgroud)
这样,您的根元素仍应由$match中的第一部分找到pipeline。
请注意,我$ifNull在第二部分中使用过滤掉“根”元素,因为在查找深度为 1 的元素时, $parentIdand$$grandparentId将为 null 或未定义。如果预期行为是应在任何深度 1 中找到所有根元素元素(如果根元素被视为兄弟元素),那么您可以摆脱它并简单地进行比较$parentId和$$grandparentId直接比较。
查找文档:https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/
| 归档时间: |
|
| 查看次数: |
503 次 |
| 最近记录: |