MongoDB聚合中$project与$match阶段未按预期工作问题
问题原因及解决方案
你的查询返回空结果的核心原因是:$match阶段的常规语法无法引用聚合阶段生成的计算字段。你在$match中写的"$firstDayOfLastMonth"会被MongoDB当成字符串字面量,而不是之前$project生成的字段引用,自然匹配不到数据。
下面是两种可行的解决方法:
方法一:用$expr在$match中实现字段比较
通过$expr包裹比较逻辑,就能让$match识别聚合生成的字段:
db.user_activity_trackings.aggregate([ { $project: { "firstDayOfLastMonth": { "$dateFromParts": { "year": { "$year": { "$dateAdd": { "startDate": "$$NOW", "unit": "month", "amount": -1 } } }, "month": { "$month": { "$dateAdd": { "startDate": "$$NOW", "unit": "month", "amount": -1 } } }, "day": 1 } }, "createdAt": 1 } }, { $match: { $expr: { $gte: ["$createdAt", "$firstDayOfLastMonth"] } } } ])
方法二:提前计算上月1日,直接作为常量过滤(更高效)
这种方式不需要为每个文档计算上月1日,能减少聚合计算开销,推荐使用:
客户端计算后传入(适合多数场景)
// 先计算上月1日的零时日期 const firstDayOfLastMonth = new Date(); firstDayOfLastMonth.setMonth(firstDayOfLastMonth.getMonth() - 1); firstDayOfLastMonth.setDate(1); firstDayOfLastMonth.setHours(0, 0, 0, 0); // 执行聚合查询 db.user_activity_trackings.aggregate([ { $match: { createdAt: { $gte: firstDayOfLastMonth } } } ])
纯聚合语法实现(不依赖客户端)
db.user_activity_trackings.aggregate([ { $match: { $expr: { $gte: [ "$createdAt", { $dateFromParts: { year: { $year: { $dateAdd: { startDate: "$$NOW", unit: "month", amount: -1 } } }, month: { $month: { $dateAdd: { startDate: "$$NOW", unit: "month", amount: -1 } } }, day: 1 } } ] } } } ])
内容的提问来源于stack exchange,提问作者Aditya
相关产品推荐
相关产品推荐

