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