我有两个收藏,
tasks
和users
。 users
集合有3个重要字段user_id
、parent_user_id
和details
。 tasks
有 user_id
字段,将其与 users
连接。
API 的要求是将相关的
users.details
与 tasks
文档一起附加,并且必须与 parent_user_id
相匹配。为此,我使用 $lookup
来匹配并放置相关的 user_details
,但由于有时 parent_user_id
可能与 user_id
不同,我必须使用 2 次查找。
第一个
$lookup
为 parent_user_id
集合中的 user_id
附加 tasks
,下一个 $lookup
使用提取的 details
附加 parent_user_id
。
我目前的管道:
[
{
'$lookup': {
'from': 'users',
'let': {
'uid': '$user_id',
'pid': '$project_id'
},
'pipeline': [
{
'$match': {
'$expr': {
'$and': [
{
'$eq': [
'$project_id', '$$pid'
]
}, {
'$eq': [
'$user_id', '$$uid'
]
}
]
}
}
}, {
'$project': {
'_id': 0,
'parent_user_id': 1
}
}
],
'as': 'parent_info'
}
}, {
'$replaceRoot': {
'newRoot': {
'$mergeObjects': [
{
'$arrayElemAt': [
'$parent_info', 0
]
}, '$$ROOT'
]
}
}
}, {
'$project': {
'parent_info': 0
}
}, {
'$lookup': {
'from': 'users',
'let': {
'pid': '$project_id',
'uid': '$parent_user_id'
},
'pipeline': [
{
'$match': {
'$expr': {
'$and': [
{
'$eq': [
'$project_id', '$$pid'
]
}, {
'$eq': [
'$user_id', '$$uid'
]
}
]
}
}
}, {
'$project': {
'_id': 0,
'details': 1
}
}
],
'as': 'user_info'
}
}, {
'$replaceRoot': {
'newRoot': {
'$mergeObjects': [
{
'$arrayElemAt': [
'$user_info', 0
]
}, '$$ROOT'
]
}
}
}, {
'$project': {
'user_info': 0,
'project_id': 0
}
}
]
这工作正常。问题是大多数时候
parent_user_id
与 user_id
相同,所以我可以在第一次查找本身中获取 details
并完全忽略第二次查找,但我无法实现它。
如有任何帮助,我们将不胜感激。
您可以通过在
is_same_user
阶段添加 $addFields
字段来实现此目的,然后使用 $match
阶段过滤掉这些用户。这是完整的查询:
db.tasks.aggregate([
{
"$lookup": {
"from": "users",
"let": {
"uid": "$user_id",
"pid": "$project_id"
},
"pipeline": [
{
"$match": {
"$expr": {
"$and": [
{
"$eq": [
"$project_id",
"$$pid"
]
}
]
}
}
},
{
"$addFields": {
"is_same_user": {
"$eq": [
"$user_id",
"$$uid"
]
},
"lookup_user_id": {
"$ifNull": [
"$parent_user_id",
"$user_id"
]
}
}
},
{
"$match": {
"$expr": {
"$or": [
{
"$and": [
{
"$eq": [
"$is_same_user",
true
]
},
{
"$eq": [
"$user_id",
"$$uid"
]
}
]
},
{
"$eq": [
"$lookup_user_id",
"$$uid"
]
}
]
}
}
},
{
"$project": {
"_id": 0,
"parent_user_id": 1,
"details": 1
}
}
],
"as": "user_info"
}
},
{
"$replaceRoot": {
"newRoot": {
"$mergeObjects": [
{
"$arrayElemAt": [
"$user_info",
0
]
},
"$$ROOT"
]
}
}
},
{
"$project": {
"user_info": 0,
"project_id": 0
}
}
])
这里是 MongoDB Playground 的链接,用于查看查询工作:https://mongoplayground.net/p/LZlM9FnVs5U