MongoDB聚合查询:关联Companies与Projects集合并嵌套项目数组
问题描述
我有两个MongoDB集合:Companies和Projects,需要编写聚合函数实现两个需求:
- 筛选出
status为"Client"的公司 - 将与公司
_id匹配的Projects文档以对象数组形式嵌套到公司文档新增的projects字段中
示例集合数据
Companies集合
{ _id: ObjectId('2341908342'), companyName: "Meta", address: "123 Facebook Lane", status: "Client" }
Projects集合
{ _id: ObjectId('234123840'), companyId: '2341908342', name: "Test Project", price: 97450, } { _id: ObjectId('23413456'), companyId: '2341908342', name: "Test Project 2", price: 100000, }
期望聚合结果
{ _id: ObjectId('2341908342'), companyName: "Meta", address: "123 Facebook Lane", projects: [ { _id: ObjectId('234123840'), companyId: '2341908342', name: "Test Project", price: 97450, }, { _id: ObjectId('23413456'), companyId: '2341908342', name: "Test Project 2", price: 100000, } ] }
现有问题
我尝试用$lookup实现,但返回的公司信息正确,projects数组始终为空,现有代码如下:
try { const allClients = await companyCollection .aggregate([ { $match: { orgId: { $in: [new ObjectId(req.user.orgId)], }, status: { $in: ["Client"], }, }, }, { $lookup: { from: "projects", let: { companyId: { $toString: [req.user.companyId], }, }, pipeline: [ { $match: { $expr: { $eq: ["$companyId", "$$companyId"], }, }, }, ], as: "projects", }, }, ]) .toArray()
问题原因与修复方案
你的代码里$lookup的let部分存在核心错误:用了req.user.companyId(当前登录用户的公司ID)而非当前遍历的客户公司文档的_id来关联项目,导致匹配逻辑完全偏离需求。
修复后的聚合代码
try { const allClients = await companyCollection .aggregate([ { $match: { orgId: new ObjectId(req.user.orgId), // $in单个值可简化为直接匹配 status: "Client" // $in单个值同样可简化 }, }, { $lookup: { from: "projects", let: { // 将当前公司文档的ObjectId类型_id转为字符串,匹配Projects中字符串类型的companyId companyIdStr: { $toString: "$_id" } }, pipeline: [ { $match: { $expr: { $eq: ["$companyId", "$$companyIdStr"] } } } ], as: "projects" } } ]) .toArray() } catch (err) { console.error(err) // 建议添加错误处理逻辑 }
关键修复点
- 关联字段修正:
let中必须引用当前公司文档的_id(即$_id),而非与业务无关的req.user.companyId - 类型匹配处理:由于Projects集合的
companyId是字符串类型,而Companies的_id是ObjectId类型,必须通过$toString转换类型后再匹配 - 条件简化:当
$in仅包含单个值时,直接使用等于匹配更简洁高效
可选简化写法(仅适用于Projects的companyId为ObjectId类型)
如果Projects集合的companyId字段是ObjectId类型,可使用更简洁的$lookup写法:
{ $lookup: { from: "projects", localField: "_id", foreignField: "companyId", as: "projects" } }
内容的提问来源于stack exchange,提问作者CameronWood23
相关产品推荐
相关产品推荐

