首页 > 解决方案 > Mongoose 使用外键在 3 个集合中查找

问题描述

我发现了一些与此相关的问题(此处此处),但我无法以一种我能理解如何做我需要的方式来解释答案。

我有 3 个集合:组织、用户和项目。每个项目属于一个用户,每个用户属于一个组织。从用户的id,我需要返回所有属于登录用户所属组织的项目。

从集合中返回属于用户的项目很容易,使用以下查询:

const projects = await Project.find({ user: req.user.id }).sort({ createdAt: -1 })

每个用户都有一个组织 ID 作为外键,我认为我需要使用 $lookup 和可能的 $unwind mongo 命令做一些事情,但与 SQL 查询不同,我真的很难理解发生了什么,因此我可以正确构造查询。

编辑:使用此查询

const orgProjects = User.aggregate(
    [
        {
            $match: { _id: req.user.id }
        },
        {
            $project: { _id: 0, org_id: 1 }
        },
        {
            $lookup: {
                from: "users",
                localField: "organisation",
                foreignField: Organisation._id,
                as: "users_of_org"
            }
        },
        {
            $lookup: {
                from: "projects",
                localField: "users_of_org._id",
                foreignField: "user",
                as: "projects"
            }
        },
        {
            $unset: ["organisation", "users_of_org"]
        },
        {
            $unwind: "$projects"
        },
        {
            $replaceWith: "$projects"
        }
    ])

似乎几乎可以工作,返回以下内容:

Aggregate {
  _pipeline: [
    { '$match': [Object] },
    { '$project': [Object] },
    { '$lookup': [Object] },
    { '$lookup': [Object] },
    { '$unset': [Array] },
    { '$unwind': '$projects' },
    { '$replaceWith': '$projects' }
  ],
  _model: Model { User },
  options: {}
}

标签: mongodbmongoose

解决方案


假设您的文档具有这样的架构您可以执行如下所示的聚合管道,其中包含 2 个$lookup阶段。

db.users.aggregate(
[
    {
        $match: { _id: "user1" }
    },
    {
        $project: { _id: 0, org_id: 1 }
    },
    {
        $lookup: {
            from: "users",
            localField: "org_id",
            foreignField: "org_id",
            as: "users_of_org"
        }
    },
    {
        $lookup: {
            from: "projects",
            localField: "users_of_org._id",
            foreignField: "user_id",
            as: "projects"
        }
    },
    {
        $unset: ["org_id", "users_of_org"]
    },
    {
        $unwind: "$projects"
    },
    {
        $replaceWith: "$projects"
    }
])

推荐阅读