Mongodb 使用外键跨3个集合进行Mongoose查找

Mongodb 使用外键跨3个集合进行Mongoose查找,mongodb,mongoose,Mongodb,Mongoose,我发现了一些与此相关的问题(和),但我无法以我能够理解如何做我需要的事情的方式来解释答案 我有3个收藏:组织、用户和项目。每个项目属于一个用户,每个用户属于一个组织。从用户id中,我需要返回属于登录用户所属组织的所有项目 通过以下查询,可以轻松地从集合中返回属于用户的项目: const projects = await Project.find({ user: req.user.id }).sort({ createdAt: -1 }) 每个用户都有一个组织id作为外键,我认为我需要使用$lo

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

我有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: {}
}

假设您的文档具有类似于的模式,您可以使用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"
    }
])

谢谢你的回答,我会尝试一下——我需要做一个聚合管道吗?我不能只通过一个查询来做吗?我不明白的一点是“$project:{{u id:0,org\u id:1}”,这行代码做了什么/来自哪里?@bevc你需要聚合查询才能在mongo中进行连接/查找。“查找”接口无法执行此操作。实际上,您可以删除$project阶段,它仍然可以工作。这只是我的一个习惯,只处理后续阶段需要的实际字段/数据。在这里,我们指定不包含用户id,只包含匹配用户的组织id。如果你跳过最初的投影,那没什么大不了的。因为它将只匹配一个文档,所以内存使用甚至不会成为一个问题。但是如果匹配阶段匹配了数千个文档,那么一个项目就有意义了suppose@bevc如果您完全控制模式,那么在项目文档上存储
org\u id
将使您能够摆脱1个查找阶段。如果您将
org_id
存储在登录用户的声明/会话/cookies/任何内容中,您也可以摆脱剩余的查找阶段,这样您就不必从数据库中获取它。@bevc您可以向mongoplayground添加一些示例数据并在此处共享链接吗?我来看看。@bevc在这里:注意:ObjectId(“xyz”)无效。只有有效的objectsid十六进制字符串才能用于
ObjectId()