MongoDB聚合查询:关联集合时保留主集全字段及子集指定字段
解决MongoDB $lookup后保留主集合全部字段并过滤关联集合字段的问题
我明白你的需求:想要在聚合查询中返回timestamps集合的全部字段,同时只返回ie_settings集合的指定字段,而不是所有字段。之前直接用$lookup会返回关联集合的所有字段,单独用$project又容易不小心丢掉主集合的字段,对吧?
这里有两种靠谱的实现方式,你可以根据自己的场景选择:
方法1:在$lookup内部使用pipeline过滤字段
这种方式更高效,因为它会在关联查询的时候就只获取需要的字段,而不是先把所有字段查出来再过滤:
Timestamp.aggregate([ // 第一步:匹配你需要的timestamps文档 { $match: { $or: [ { current_status: '60min break now' }, { current_status: 'Time out' } ], createdAt: { $gte: date_from, $lt: date_to } } }, // 第二步:关联ie_settings并指定要返回的字段 { $lookup: { from: "ie_settings", // 你的关联集合名称 localField: "关联字段名", // timestamps中用来关联的字段,比如ie_settings_id foreignField: "_id", // ie_settings中对应的关联字段 as: "ie_settings", // 关联结果的数组字段名 pipeline: [ // 在这里指定只需要ie_settings的哪些字段,比如field1、field2 { $project: { _id: 1, // 如果需要_id就保留,不需要可以设为0 field1: 1, field2: 1, // 继续添加你需要的其他字段 } } ] } } ])
方法2:在$lookup之后用$project保留主集合字段并过滤关联字段
如果你更习惯在关联后处理,可以用这种方式,注意要通过$$ROOT保留timestamps的所有字段:
Timestamp.aggregate([ { $match: { $or: [ { current_status: '60min break now' }, { current_status: 'Time out' } ], createdAt: { $gte: date_from, $lt: date_to } } }, { $lookup: { from: "ie_settings", localField: "关联字段名", foreignField: "_id", as: "ie_settings" } }, // 第三步:保留timestamps全部字段,同时过滤ie_settings的字段 { $project: { // 保留timestamps的所有字段 ...$$ROOT, // 重新定义ie_settings字段,只保留需要的部分 ie_settings: { $map: { input: "$ie_settings", as: "setting", in: { _id: "$$setting._id", field1: "$$setting.field1", field2: "$$setting.field2" // 按需添加字段 } } } } } ])
关键注意点:
- 方法1的
pipeline参数是MongoDB 3.6+支持的,如果你用的是旧版本,只能用方法2。 - 替换代码中的
关联字段名为你实际用来关联两个集合的字段(比如timestamps里的ie_setting_id对应ie_settings的_id)。 - 如果
ie_settings的关联结果是单个文档(不是数组),可以在$lookup后加$unwind,然后在$project里直接指定字段,不用$map。
内容的提问来源于stack exchange,提问作者noyruto88
相关产品推荐
相关产品推荐

