如何在Mongoose聚合管道中排除关联文档的指定字段?
如何在Mongoose聚合的$lookup中保留原文档字段并过滤关联文档字段?
需求场景
使用Mongoose聚合管道的$lookup关联Task和Case文档时,需要保留Task的所有字段,同时仅保留关联Case文档中的case_id和case_number字段,排除Case的其他字段。
数据模型
Task Schema
const mongoose = require('mongoose'); const taskSchema = mongoose.Schema({ case: { type: mongoose.Schema.Types.ObjectId, ref: "Case" }, task_field_2: { type: String }, task_field_3: { type: String }, // ... 更多Task字段 task_field_N: { type: String } }) module.exports = mongoose.model('Task', taskSchema);
Case Schema
const mongoose = require("mongoose"); const caseSchema = new mongoose.Schema({ case_id: { type: Number, unique: true, }, case_number: { type: String, }, case_field_2: { type: String }, case_field_3: { type: String }, // ... 更多Case字段 case_field_N: { type: String } }) module.exports = mongoose.model('Case', caseSchema);
问题分析
直接使用$project仅指定case.case_id和case.case_number为1,会默认排除Task的所有其他字段,不符合需求。
解决方案
有两种常用方式可以实现需求:
方式一:在$lookup阶段直接过滤字段
利用$lookup的pipeline子阶段,在关联查询Case时就筛选出需要的字段,避免后续额外处理:
Task.aggregate([ { $lookup: { from: "cases", // 注意这里是MongoDB集合名,通常为模型名的小写复数形式 localField: "case", foreignField: "_id", as: "case", pipeline: [ { $project: { case_id: 1, case_number: 1, _id: 0 // 不需要Case的_id可添加此行,需要则删除 } } ] } }, // 将$lookup返回的case数组转为单个对象(适用于单关联场景) { $unwind: { path: "$case", preserveNullAndEmptyArrays: true // 保留未关联Case的Task文档 } } ])
方式二:先保留所有字段,再替换关联字段
如果已完成$lookup,可以在$project阶段通过$$ROOT保留Task的全部原始字段,再覆盖case字段为过滤后的内容:
Task.aggregate([ { $lookup: { from: "cases", localField: "case", foreignField: "_id", as: "case" } }, { $unwind: { path: "$case", preserveNullAndEmptyArrays: true } }, { $project: { // 展开当前文档的所有原始字段 ..."$$ROOT", // 重新定义case字段,仅保留指定属性 case: { case_id: "$case.case_id", case_number: "$case.case_number" } } } ])
内容的提问来源于stack exchange,提问作者Harshil Sharma
相关产品推荐
相关产品推荐

