मेरा मानना है कि स्तर फ़ील्ड हम $reduce का उपयोग करके एक सरणी से पदानुक्रमित संरचना बना सकते हैं। इसे प्राप्त करने के लिए हमें reportees
. प्राप्त करने की आवश्यकता है $graphLookup
. के बाद अवरोही स्तर के अनुसार क्रमित . दुर्भाग्य से वर्तमान में ऐसा करने का एकमात्र तरीका $unwind + $sort + $group का उपयोग करना है जो एकत्रीकरण को काफी लंबा बनाता है।
फिर हम $reduce
. का उपयोग करके उस ऑर्डर किए गए ऐरे को प्रोसेस कर सकते हैं . प्रत्येक चरण में हमें केवल एक कर्मचारी को उसके reportees
. सहित परिणाम सेट में जोड़ना होगा पिछले स्तर से। इसके अतिरिक्त हमें यह पता लगाने की आवश्यकता है कि level
. कब हमारे प्रसंस्करण के दौरान परिवर्तन और उस स्थिति में सहायक सरणियों को पुनर्व्यवस्थित करें।
$addFields बस मौजूदा reportees
. को बदल देता है इस मामले में क्षेत्र। $concatArrays हमें वर्तमान कर्मचारी को जोड़ने की अनुमति देता है ($$this
) परिणाम के लिए। $filter का उपयोग करके हम reportees
प्राप्त कर सकते हैं निचले स्तर से।
db.getCollection('employees').aggregate([
{
$match: {
empId : "10"
}
},
{
$graphLookup: {
from: "employees",
startWith: "$empId",
connectFromField: "empId",
connectToField: "managerId",
as: "reportees",
maxDepth: 4,
depthField: "level"
}
},
{
$project: {
"empId":1,
"managerId":1,
"reportees.empId":1,
"reportees.name":1,
"reportees.managerId":1,
"reportees.level":1
}
},
{
$unwind: "$reportees"
},
{
$sort: { "reportees.level": -1 }
},
{
$group: {
_id: "$_id",
empId: { $first: "$empId" },
managerId: { $first: "$managerId" },
reportees: { $push: "$reportees" }
}
},
{
$addFields: {
reportees: {
$reduce: {
input: "$reportees",
initialValue: {
currentLevel: -1,
currentLevelEmployees: [],
previousLevelEmployees: []
},
in: {
$let: {
vars: {
prev: {
$cond: [
{ $eq: [ "$$value.currentLevel", "$$this.level" ] },
"$$value.previousLevelEmployees",
"$$value.currentLevelEmployees"
]
},
current: {
$cond: [
{ $eq: [ "$$value.currentLevel", "$$this.level" ] },
"$$value.currentLevelEmployees",
[]
]
}
},
in: {
currentLevel: "$$this.level",
previousLevelEmployees: "$$prev",
currentLevelEmployees: {
$concatArrays: [
"$$current",
[
{ $mergeObjects: [
"$$this",
{ reportees: { $filter: { input: "$$prev", as: "e", cond: { $eq: [ "$$e.managerId", "$$this.empId" ] } } } }
] }
]
]
}
}
}
}
}
}
}
},
{
$addFields: { reportees: "$reportees.currentLevelEmployees" }
}
]).pretty()
उपरोक्त समाधान कई स्तरों के लिए काम करना चाहिए। आउटपुट:
{
"_id" : "10",
"empId" : "10",
"managerId" : "15",
"reportees" : [
{
"empId" : "6",
"name" : "Employee6",
"managerId" : "10",
"level" : NumberLong(0),
"reportees" : [
{
"empId" : "1",
"name" : "Employee1",
"managerId" : "6",
"level" : NumberLong(1),
"reportees" : [ ]
},
{
"empId" : "2",
"name" : "Employee2",
"managerId" : "6",
"level" : NumberLong(1),
"reportees" : [ ]
}
]
},
{
"empId" : "8",
"name" : "Employee8",
"managerId" : "10",
"level" : NumberLong(0),
"reportees" : [
{
"empId" : "5",
"name" : "Employee5",
"managerId" : "8",
"level" : NumberLong(1),
"reportees" : [ ]
},
{
"empId" : "4",
"name" : "Employee4",
"managerId" : "8",
"level" : NumberLong(1),
"reportees" : [ ]
}
]
}
]
}