Вы можете изменить его на несколько шагов:
- Найти массив прямых асцендентов (родитель, прародитель и т. Д. c.)
- Найти непосредственных потомков каждого прародителя и «выше» (тем самым давая вам родных братьев и сестер, родных братьев и сестер и т. д. c.)
- Объедините два массива в один набор (таким образом, обеспечивая уникальность)
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"]}
}}
])
См. Как вычислить sh значение нескольких столбцов в группе относительно $setUnion
.
Оригинальный ответ:
Если вас интересует только родитель и его братья и сестры, вы можете использовать $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'
}}
])
Таким образом, ваш root элемент все еще должен быть найден первой частью $match
в pipeline
.
Обратите внимание, что я использую $ifNull
во второй части, чтобы отфильтровать элементы "root", так как $parentId
и $$grandparentId
будут иметь значение null или un определяется при поиске элемента на глубине 1. Если предполагается, что все элементы root должны быть найдены для любого элемента глубины 1 (если элементы root считаются братьями и сестрами), то вы можете избавиться от него и просто сравнить $parentId
и $$grandparentId
прямо вверх.
Документы для поиска: https://docs.mongodb.com/manual/reference/operator/aggregation/lookup/