我有两个集Employee
,Client
Employee
架构有以下记录
{
"_id": ObjectId("5a852dcd0290f7eca89e9a79"),
"FirstName": "Nirav",
"LastName": "Modi",
"Gender": true,
"Forms": [{
"ClientId": ObjectId("5a8528ed0290f7eca89e9a5f"),
"ProjectId": ObjectId("5a856fde0290f7eca89e9a88"),
"FormId": ObjectId("5a62e561f6647f17f85e54c5")
}]
}
Client
架构有以下记录
{
"_id" : ObjectId("5a8528ed0290f7eca89e9a5f"),
"CompanyName" : "PNB",
"Projects" : [{
"_id" : ObjectId("5a856ca70290f7eca89e9a7f"),
"Name" : "House Loan",
"Description" : "Get house load",
"Forms" : []
}, {
"_id" : ObjectId("5a856fde0290f7eca89e9a88"),
"Name" : "Car Loan",
"Description" : "get car loan",
"Forms" : [
ObjectId("5a62e82299d9fe0a14a1ead5"),
ObjectId("5a6eec263bf43426d4d31780"),
ObjectId("5a62e561f6647f17f85e54c5")
]
}
]
}
在我的系统中,会为员工分配表格。正如您所见,员工架构包含Forms
字段,其中包含ClientId
,ProjectId
,FormId
。
表单可以在多个客户端中进行多个项目。
当我获取数据时,我希望输出如下所示
{
"_id": ObjectId("5a852dcd0290f7eca89e9a79"),
"FirstName": "Aartik",
"LastName": "Ladumor",
"Gender": true,
"Clients": [{
"_id": ObjectId("5a8528ed0290f7eca89e9a5f"),
"CompanyName": "PNB",
"Projects": [{
"_id": ObjectId("5a856fde0290f7eca89e9a88"),
"Name": "Car Loan",
"Description": "get car loan",
"Forms": [
ObjectId("5a62e82299d9fe0a14a1ead5"),
ObjectId("5a6eec263bf43426d4d31780"),
ObjectId("5a62e561f6647f17f85e54c5")
]
}
]
}
]
}
仅获取项目中包含分配给员工的表单的客户。
为此我正在进行聚合,如下所示
db.Employees.aggregate([{
$lookup: {
from: "Clients",
localField: "Forms.ClientId",
foreignField: "_id",
as: "Clients"
}
}, {
filter projects array in matched client contains only
projects that match Employee.Forms each elements
ProjectsId -> Client.Projects._id and
FormId -> in Client.Projects.Forms array containing forms ObjectId
}
]).pretty()
答案 0 :(得分:1)
您可以尝试以下聚合
db.employees.aggregate([
{ $unwind: "$Forms" },
{
$lookup: {
from: "clients",
localField: "Forms.ClientId",
foreignField: "_id",
as: "Clients"
}
},
{ $unwind: "$Clients" },
{ $unwind: "$Clients.Projects" },
{
$redact: {
$cond: {
if: { $eq: [ "$Forms.ProjectId", "$Clients.Projects._id" ] },
then: "$$KEEP",
else: "$$PRUNE"
}
}
},
{
$group: {
_id: {
_id: "$_id",
ClientId: "$Clients._id"
},
FirstName: { $first: "$FirstName" },
LastName: { $first: "$LastName" },
Gender: { $first: "$Gender" },
Client: { $first: "$Clients" },
Projects: { $push: "$Clients.Projects" }
}
},
{
$group: {
_id: "$_id._id",
FirstName: { $first: "$FirstName" },
LastName: { $first: "$LastName" },
Gender: { $first: "$Gender" },
Clients: { $push: {
_id: "$Client._id",
CompanyName: "$Client.CompanyName",
Projects: "$Projects"
} }
}
}
])
基本上你必须多次使用$unwind,因为你需要比较值而不是数组。所以$ lookup合并了两个集合。然后你需要比较项目ID,所以你必须再次展开$。要筛选出不属于员工的项目,您可以使用$redact来比较两个字段。然后最终得到两级嵌套数组,你应该使用$ group。
答案 1 :(得分:1)
尝试此聚合,我们$lookup
来自员工集合的客户端ID,然后是$filter
来自匹配客户的项目和表单ID
db.Employee.aggregate(
[
{$lookup : {
from : "Client",
localField : "Forms.ClientId",
foreignField : "_id",
as : "Clients"
}},
{$addFields : {
"Clients.Projects" : {
$filter : {
input : {$arrayElemAt : ["$Clients.Projects", 0]},
as : "project",
cond : {$and : [
{$eq : [{$arrayElemAt : ["$Forms.ProjectId", 0]}, "$$project._id"]},
{$in : [{$arrayElemAt : ["$Forms.FormId", 0]}, "$$project.Forms"]}
]}}
}
}}
]
).pretty()