如何用Mongoose Aggregate实现$gte和$lte日期范围查询?
问题
使用Mongoose 5.11.15查询数据时,find方法结合$and、$gte、$lte条件可以正常获取test_id匹配且createdAt在指定日期范围内的数据,但改用aggregate的$match阶段时,却无法返回任何数据——仅保留test_id条件时能正常查询。
原find方法代码
let datas = await Data.find({ '$and': [ { test_id: testId }, { createdAt: { $gte: moment(req.query.from).startOf('day') } }, { createdAt: { $lte: moment(req.query.to).endOf('day') } } ], });
尝试的aggregate代码
const datas = await Data.aggregate([ { '$match': { '$and': [ { test_id: testId }, { createdAt: { $gte: moment(req.query.from).startOf('day') } }, { createdAt: { $lte: moment(req.query.to).endOf('day') } } ], } } ]);
Schema定义
const Data = new Schema({ test_id: { type: String, required: true, }, user_id: { type: String, required: true, }, item: { agent_id: { type: String, ref: 'Company' }, product_no: { type: String, required: true }, user_id: { type: String, required: true, ref: 'User' }, name: { type: String, required: true }, quantity: { type: Number, required: true }, standard_price: { type: Number}, designation: { type: String }, category: { type: String }, weight: { type: Number }, materials: { type: String }, remarks: { type: String }, note: { type: String }, location: String, image: String } }, { timestamps: true, });
解决方案
问题出在aggregate的$match阶段中,$and数组里重复定义了createdAt字段。MongoDB的查询文档不允许同一个键在一个对象中重复出现,后定义的键会覆盖前一个,导致实际生效的条件只有单个范围限制,自然查不到符合日期区间的数据。而find方法中Mongoose会自动帮你合并同一个字段的多个条件,所以能正常工作。
修改方法是将createdAt的$gte和$lte条件合并到同一个对象中,同时$and可以省略(MongoDB默认多个条件就是逻辑与的关系):
const datas = await Data.aggregate([ { '$match': { test_id: testId, createdAt: { $gte: moment(req.query.from).startOf('day'), $lte: moment(req.query.to).endOf('day') } } } ]);
如果一定要保留$and写法,也需要把createdAt的条件合并:
const datas = await Data.aggregate([ { '$match': { '$and': [ { test_id: testId }, { createdAt: { $gte: moment(req.query.from).startOf('day'), $lte: moment(req.query.to).endOf('day') } } ] } } ]);
这样修改后,aggregate的查询逻辑就和find方法完全一致,能正确返回符合条件的数据。
内容的提问来源于stack exchange,提问作者Masahiro Hanawa
相关产品推荐
相关产品推荐

