Mongo 具有嵌套嵌入文档和 $project 的聚合管道 $lookup
Mongo Aggregation Pipeline $lookup with nested embedded documents and $project
我有两个集合 users
和 `groups。让我们假装集合中当前包含以下数据。
users
集合有以下文档
{
"_id":"57a944390b1acf0d069388c1",
"first":"John",
"last":"Smith",
"email":"John.Smith@gmail.com",
"groups":[
{
"id":"57aab09c0b1acf135a6b6856",
"name":"Group A"
},
{
"id":"57aab0ed0b1acf135a6b6857",
"name":"Group B"
},
{
"id":"57b008be31a5a202ee4ff47b",
"name":"Group C"
}
]
}
groups
集合有以下两个文档
[
{
"_id":"57aab0ed0b1acf135a6b6857",
"name":"Group B",
"requests":[
{
"_id":"57b14b1831a5a2756fbc9873",
"description":"Request A",
"denied_requests":[ ]
}
]
} {
"_id":"57b008be31a5a202ee4ff47b",
"name":"Group C",
"requests":[
{
"_id":"57b14c2131a5a2756fbc9874",
"description":"Request B",
"denied_requests":[ ]
},
{
"_id":"57b14e3131a5a2756fbc9875",
"description":"Request C",
"denied_requests":[
"57a944390b1acf0d069388c1"
]
}
]
}
]
我需要做的是使用聚合管道查询用户的所有请求,不包括用户已拒绝的请求。
我想这将包括以下 psudo 步骤,将 user_id
作为问题的输入。
$match
在用户 _id
字段上
$project
组 id
来自上一步的结果
$lookup
使用 $project
中 users.groups
中 groups
集合的 _id
中的 id
$match
在 requests
上根据要求在 denied_requests
数组中没有当前用户 ID。
样本输入
示例输入为 57a944390b1acf0d069388c1
,代表用户 _id
示例输出
示例输出为以下用户未拒绝的请求列表。
[
{
"_id":"57b14b1831a5a2756fbc9873",
"description":"Request A",
"denied_requests":[]
},
{
"_id":"57b14c2131a5a2756fbc9874",
"description":"Request B",
"denied_requests":[ ]
}
]
运行 下面的管道,它应该会给你想要的结果:
var userId = "57a944390b1acf0d069388c1";
db.users.aggregate([
{ "$match": { "_id": userId } },
{ "$unwind": "$groups" },
{
"$lookup": {
"from": "groups",
"localField": "groups.id",
"foreignField": "_id",
"as": "group"
}
},
{ "$unwind": "$group" },
{
"$project": {
"requests": {
"$filter": {
"input": "$group.requests",
"as": "item",
"cond": { "$not": {
"$setIsSubset": [
[userId], "$$item.denied_requests"
]
} }
}
}
}
},
{ "$unwind": "$requests" },
{
"$project": {
"_id": "$requests._id",
"description": "$requests.description",
"denied_requests": "$requests.denied_requests"
}
}
])
我有两个集合 users
和 `groups。让我们假装集合中当前包含以下数据。
users
集合有以下文档
{
"_id":"57a944390b1acf0d069388c1",
"first":"John",
"last":"Smith",
"email":"John.Smith@gmail.com",
"groups":[
{
"id":"57aab09c0b1acf135a6b6856",
"name":"Group A"
},
{
"id":"57aab0ed0b1acf135a6b6857",
"name":"Group B"
},
{
"id":"57b008be31a5a202ee4ff47b",
"name":"Group C"
}
]
}
groups
集合有以下两个文档
[
{
"_id":"57aab0ed0b1acf135a6b6857",
"name":"Group B",
"requests":[
{
"_id":"57b14b1831a5a2756fbc9873",
"description":"Request A",
"denied_requests":[ ]
}
]
} {
"_id":"57b008be31a5a202ee4ff47b",
"name":"Group C",
"requests":[
{
"_id":"57b14c2131a5a2756fbc9874",
"description":"Request B",
"denied_requests":[ ]
},
{
"_id":"57b14e3131a5a2756fbc9875",
"description":"Request C",
"denied_requests":[
"57a944390b1acf0d069388c1"
]
}
]
}
]
我需要做的是使用聚合管道查询用户的所有请求,不包括用户已拒绝的请求。
我想这将包括以下 psudo 步骤,将 user_id
作为问题的输入。
$match
在用户_id
字段上$project
组id
来自上一步的结果$lookup
使用$project
中users.groups
中groups
集合的_id
中的id
$match
在requests
上根据要求在denied_requests
数组中没有当前用户 ID。
样本输入
示例输入为 57a944390b1acf0d069388c1
,代表用户 _id
示例输出
示例输出为以下用户未拒绝的请求列表。
[
{
"_id":"57b14b1831a5a2756fbc9873",
"description":"Request A",
"denied_requests":[]
},
{
"_id":"57b14c2131a5a2756fbc9874",
"description":"Request B",
"denied_requests":[ ]
}
]
运行 下面的管道,它应该会给你想要的结果:
var userId = "57a944390b1acf0d069388c1";
db.users.aggregate([
{ "$match": { "_id": userId } },
{ "$unwind": "$groups" },
{
"$lookup": {
"from": "groups",
"localField": "groups.id",
"foreignField": "_id",
"as": "group"
}
},
{ "$unwind": "$group" },
{
"$project": {
"requests": {
"$filter": {
"input": "$group.requests",
"as": "item",
"cond": { "$not": {
"$setIsSubset": [
[userId], "$$item.denied_requests"
]
} }
}
}
}
},
{ "$unwind": "$requests" },
{
"$project": {
"_id": "$requests._id",
"description": "$requests.description",
"denied_requests": "$requests.denied_requests"
}
}
])