Mongodb $loopkup:仅查找满足条件的文档

问题描述 投票:0回答:1

我有两个收藏,

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
并完全忽略第二次查找,但我无法实现它。

如有任何帮助,我们将不胜感激。

python mongodb aggregation-framework
1个回答
1
投票

您可以通过在

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

© www.soinside.com 2019 - 2024. All rights reserved.