MongoDB中$filter结合$or未按预期工作的问题排查
MongoDB 统计符合条件的URL数量解决方案
问题分析
你遇到的$filter失效问题,核心原因是条件表达式中数组元素的字段引用错误,或是日期过期的比较逻辑未正确实现,导致筛选条件未生效,返回了全部URL数量。
正确聚合管道实现
以下聚合管道可实现需求:统计每个文档中Urls和DraftUrls数组里,Status为Inactive或Validity已过期的URL总数,同时保留GroupName和TemplateName字段:
db.Pages.aggregate([ { $addFields: { // 合并两个URL数组,统一处理筛选逻辑 allUrls: { $concatArrays: ["$Urls", "$DraftUrls"] } } }, { $addFields: { // 筛选符合条件的URL元素 filteredUrls: { $filter: { input: "$allUrls", cond: { $or: [ { $eq: ["$$this.Status", "Inactive"] }, { $lt: ["$$this.Validity", $$NOW] } // 用内置变量$$NOW判断日期是否过期 ] } } } } }, { $project: { GroupName: 1, TemplateName: 1, invalidUrlCount: { $size: "$filteredUrls" } // 统计筛选后的URL数量 } } ])
关键细节说明
- 数组合并:通过
$concatArrays将Urls和DraftUrls合并为一个数组,避免重复编写两次筛选逻辑,简化代码。 - 字段引用正确姿势:在
$filter的cond中,必须用$$this指代当前遍历的数组元素(比如$$this.Status、$$this.Validity),这是确保筛选条件生效的核心。 - 日期过期判断:使用MongoDB内置变量
$$NOW获取当前服务器时间,直接与Validity字段做小于比较,准确判断URL是否过期。 - 数量统计:通过
$size获取筛选后数组的长度,即可得到符合条件的URL总数。
如果需要分别统计Urls和DraftUrls的符合条件数量,可拆分筛选逻辑:
db.Pages.aggregate([ { $addFields: { filteredUrls: { $filter: { input: "$Urls", cond: { $or: [ { $eq: ["$$this.Status", "Inactive"] }, { $lt: ["$$this.Validity", $$NOW] } ] } } }, filteredDraftUrls: { $filter: { input: "$DraftUrls", cond: { $or: [ { $eq: ["$$this.Status", "Inactive"] }, { $lt: ["$$this.Validity", $$NOW] } ] } } } } }, { $project: { GroupName: 1, TemplateName: 1, invalidUrlCount: { $size: "$filteredUrls" }, invalidDraftUrlCount: { $size: "$filteredDraftUrls" }, totalInvalidCount: { $add: [{ $size: "$filteredUrls" }, { $size: "$filteredDraftUrls" }] } } } ])
内容的提问来源于stack exchange,提问作者Hmmmmm
相关产品推荐
相关产品推荐

