MongoDB中$project与$subtract后$match返回空结果问题
解决MongoDB聚合筛选子文档时间问题
我来帮你搞定这个问题!你的聚合查询返回空结果,核心原因是**$match阶段没办法直接引用管道里之前生成的字段(比如你定义的$past_month)**。$match默认只能匹配集合的原始字段或者固定常量,没法直接用管道中计算出来的变量——这就是为什么你换成具体的ISODate值就能得到结果的原因。
下面给你两种可行的解决方案,第二种性能更优:
方案1:用$expr让$match支持管道字段比较
通过$expr表达式,我们可以在$match里使用聚合逻辑,从而实现两个管道字段的对比:
db.collection.aggregate([ { $project: { "past_month": { $subtract: ["$created_time", 2629746000] }, // 一个月的毫秒数 "created_time": "$created_time", "posts": "$posts" } }, { $unwind: '$posts' }, { $match: { $expr: { $gte: ["$posts.created_time", "$past_month"] } } }, { "$group": { "_id": "$_id", "posts": { "$push": "$posts" }, "created_time": { "$first": "$created_time" } // 保留根节点的原始创建时间 } } ])
方案2:用$filter直接过滤数组(推荐)
这种方法不需要拆分再重组数组,直接在原数组上筛选符合条件的子文档,性能会好很多:
db.collection.aggregate([ { $addFields: { "past_month": { $subtract: ["$created_time", 2629746000] }, "posts": { $filter: { input: "$posts", as: "post", cond: { $gte: ["$$post.created_time", "$past_month"] } } } } }, // 可选:如果不需要保留past_month字段,用这个阶段移除它 { $project: { past_month: 0 } } ])
简单总结下:第一种方案是在你的原有逻辑上做修正,第二种则是利用MongoDB的数组过滤操作符,更高效地完成需求。
内容的提问来源于stack exchange,提问作者BrTkCa
相关产品推荐
相关产品推荐

