MongoDB聚合$match过滤qualification ID返回空数组问题排查
问题排查与解决
核心原因
你遇到的问题是三个常见的MongoDB聚合查询错误共同导致的:
- 字段覆盖:
$lookup配置中as: 'qualification'会直接覆盖UserQualification表原有的qualification字段(原字段存储的是Qualification的ObjectId),$unwind后该字段变为完整的Qualification文档对象,不再是ID值。 - 类型不匹配:MongoDB默认存储的
_id是ObjectId类型,你传入的字符串ID和ObjectId类型不相等,无法命中匹配。 - 语法错误:
$match中$and数组内的每一项条件都需要单独包裹为对象,你当前的写法不符合语法规范。
修复方案
方案1:保留原ID字段(推荐)
修改$lookup的输出字段名,避免覆盖原ID字段,同时做ID类型转换:
const mongoose = require('mongoose'); db.UserQualifications.aggregate([ { $lookup: { from: 'qualifications', localField: 'qualification', foreignField: '_id', as: 'qualification_detail', // 改名避免覆盖原字段 }, }, { $unwind: '$qualification_detail', }, { $match: { $and: [ { 'qualification_detail.fleet': { $in: ["Fleet A", "Fleet C"], } }, { expiry_date: { $lt: req.body.expiry_date, } }, { qualification: { // 字符串ID转ObjectId类型 $in: [mongoose.Types.ObjectId("6033e4129070031c07fbbf29")] } } ] }, } ])
方案2:不修改关联输出字段名
如果你需要保留qualification作为关联后的字段名,直接匹配子属性_id并做类型转换即可:
const mongoose = require('mongoose'); db.UserQualifications.aggregate([ { $lookup: { from: 'qualifications', localField: 'qualification', foreignField: '_id', as: 'qualification', }, }, { $unwind: '$qualification', }, { $match: { $and: [ { 'qualification.fleet': { $in: ["Fleet A", "Fleet C"], } }, { expiry_date: { $lt: req.body.expiry_date, } }, { 'qualification._id': { $in: [mongoose.Types.ObjectId("6033e4129070031c07fbbf29")] } } ] }, } ])
内容的提问来源于stack exchange,提问作者Matt Price
相关产品推荐
相关产品推荐

