Mongoose中基于$lookup条件查询获取父文档状态为Approved的子文档问题求助
解决Timesheet子文档的过滤查询问题
我来帮你排查一下为什么你的聚合查询返回空数组,这里有几个关键的错误点,咱们逐一修正:
错误分析
- 集合名称错误:
$lookup的from参数需要填写MongoDB中实际的集合名称,而不是Mongoose的模型名。Mongoose默认会将模型名转换为复数小写形式,比如你的Timesheet模型对应的集合应该是timesheets,而不是timesheetModel。 - 匹配逻辑错误:你在子管道的
$match里错误地将父文档的weekNum和子文档的parentId做对比,但我们实际需要匹配的是父文档的_id等于子文档的parentId。另外,let定义的变量在子管道中必须用$$前缀引用,而不是$。 - 数据类型不匹配:你的子Schema中
parentId是String类型,但父文档的_id是ObjectId类型,直接比较会导致匹配失败,需要做类型转换。
修正后的查询方案
方案1:不修改Schema,在聚合中处理类型转换
这种适合暂时不想改动Schema的情况,通过$toString将父文档的_id转为字符串再和子文档的parentId比较:
const result = await TimesheetIndividualData.aggregate([ { "$lookup": { "from": "timesheets", // 替换为实际的集合名称 "let": { "childParentId": "$parentId" }, "pipeline": [ { "$match": { "status": "Approved", "$expr": { "$eq": [{ "$toString": "$_id" }, "$$childParentId"] } } } ], "as": "timesheet" } }, { "$match": { "timesheet": { "$ne": [] } } } // 过滤掉未匹配到已审批父文档的记录 ])
方案2:修改Schema统一数据类型(推荐)
更高效的方式是将子Schema中的parentId改为ObjectId类型,和父文档的_id保持一致,这样查询时不需要额外的类型转换:
修改子集合Schema:
const TimesheetDataSchema = new Schema( { workingDate: { type: Date, }, dayVal: { type: Number, }, user: { type: Schema.Types.ObjectId, ref: userModel }, parentId: { type: Schema.Types.ObjectId, ref: "Timesheet" } // 改为ObjectId类型并关联父模型 }, { timestamps: true } );
对应的聚合查询可以简化为:
const result = await TimesheetIndividualData.aggregate([ { "$lookup": { "from": "timesheets", "let": { "childParentId": "$parentId" }, "pipeline": [ { "$match": { "status": "Approved", "$expr": { "$eq": ["$_id", "$$childParentId"] } } } ], "as": "timesheet" } }, { "$match": { "timesheet": { "$ne": [] } } } ])
为什么原查询返回空数组?
原查询因为集合名称错误导致无法找到父集合,加上匹配逻辑完全偏离需求,所以没有任何父文档被匹配到,最后经过$match过滤后就返回了空数组。
内容的提问来源于stack exchange,提问作者raju
相关产品推荐
相关产品推荐

