MongoDB/Mongoose嵌套Schema日期查询返回超范围结果求助
嵌套数组文档查询异常的解决方案
你遇到的问题应该是查询返回的结果只包含了嵌套数组里第一个符合日期条件的任务,而非所有符合要求的任务项吧?先把你的相关代码和查询语句整理出来,方便我们分析:
你的Schema定义
var taskSchema = new mongoose.Schema({ name: String, done: Boolean, dueDate: Date, info: String }); var eventSchema = new mongoose.Schema({ tasks: [ taskSchema ], }, { usePushEach: true });
你执行的查询语句
db.getCollection('events').find( { 'tasks.dueDate': { $gte: new ISODate('2018-04-01T00:00:00'), $lte: new ISODate('2018-05-01T00:00:00') } }, { 'tasks.$': 1, _id: 1 } )
问题根源
这里的tasks.$投影操作符是MongoDB的默认行为——它只会返回数组中第一个匹配查询条件的元素,这就是你觉得结果异常的核心原因。
解决方案
如果想要返回数组中所有符合日期范围的任务,需要借助MongoDB的聚合框架来实现,具体步骤如下:
- 先用
$match筛选出包含符合条件任务的事件文档 - 再用
$project结合$filter过滤出数组里所有符合日期要求的任务项
对应的聚合查询语句如下:
db.getCollection('events').aggregate([ // 第一步:筛选出存在符合日期任务的事件 { $match: { 'tasks.dueDate': { $gte: new ISODate('2018-04-01T00:00:00'), $lte: new ISODate('2018-05-01T00:00:00') } } }, // 第二步:过滤出数组中所有符合条件的任务 { $project: { _id: 1, tasks: { $filter: { input: '$tasks', as: 'task', cond: { $and: [ { $gte: ['$$task.dueDate', new ISODate('2018-04-01T00:00:00')] }, { $lte: ['$$task.dueDate', new ISODate('2018-05-01T00:00:00')] } ] } } } } } ])
补充说明
只要你的MongoDB版本在3.2及以上,$filter操作符就可以正常使用。如果是用Mongoose代码执行这个逻辑,只需要把上述聚合数组传给对应Model的aggregate()方法即可。
内容的提问来源于stack exchange,提问作者Wendell Pereira
相关产品推荐
相关产品推荐

