MongoDB无匹配数据时返回默认值的实现方法
MongoDB聚合查询:无匹配数据时返回默认结果
问题描述
用户现有聚合查询用于统计指定meal ID中未完成(mealsStatus不等于'SERVED')的订单数量,代码如下:
db.meals .aggregate([ { $match: { _id: { $in: [ObjectId('123'), ObjectId('1234')]}, mealsStatus: { $ne: 'SERVED' }, }, }, { $group: { _id: '$orderId', orderCount: { $sum: 1 }, }, }, ])
当前问题:当没有数据匹配$match条件时,查询无任何返回结果。需要修改查询,使其返回指定ID对应的默认数据,格式示例如下:
{ '_id': '123', 'orderCount': 0 }, { '_id': '1234', 'orderCount': 0 }
解决方案
要实现无匹配时返回默认值,可通过合并实际统计结果与默认数据集的方式实现,以下提供两种适配不同MongoDB版本的方案:
方案1:使用$unionWith(MongoDB 4.4+)
该方案通过$unionWith合并实际统计结果与构造的默认数据集,再去重保留有效数值:
const targetMealIds = [ObjectId('123'), ObjectId('1234')]; db.meals.aggregate([ // 原有统计逻辑:获取匹配数据的订单数量 { $match: { _id: { $in: targetMealIds }, mealsStatus: { $ne: 'SERVED' } } }, { $group: { _id: '$_id', orderCount: { $sum: 1 } } }, // 合并默认数据集:生成所有指定ID的默认文档(orderCount=0) { $unionWith: { coll: 'meals', pipeline: [ { $project: { _id: 0, mealId: { $literal: targetMealIds } } }, { $unwind: '$mealId' }, { $project: { _id: '$mealId', orderCount: { $literal: 0 } } } ] } }, // 去重处理:优先保留实际统计值,无统计值则保留默认0 { $group: { _id: '$_id', orderCount: { $max: '$orderCount' } } } ])
- 核心逻辑:
$max会优先取实际统计的正数值,无统计结果时则保留默认的0,确保每个指定ID都有返回。
方案2:使用$facet(兼容MongoDB 4.4以下版本)
通过$facet同时处理实际统计和默认数据,再合并去重:
const targetMealIds = [ObjectId('123'), ObjectId('1234')]; db.meals.aggregate([ { $facet: { // 统计有匹配的数据 actualCounts: [ { $match: { _id: { $in: targetMealIds }, mealsStatus: { $ne: 'SERVED' } } }, { $group: { _id: '$_id', orderCount: { $sum: 1 } } } ], // 生成默认数据集 defaultCounts: [ { $limit: 1 }, { $project: { _id: 0, mealIds: { $literal: targetMealIds } } }, { $unwind: '$mealIds' }, { $project: { _id: '$mealIds', orderCount: { $literal: 0 } } } ] } }, // 合并两个结果数组 { $project: { combined: { $concatArrays: ['$actualCounts', '$defaultCounts'] } } }, { $unwind: '$combined' }, // 去重并保留有效数值 { $group: { _id: '$combined._id', orderCount: { $max: '$combined.orderCount' } } } ])
内容的提问来源于stack exchange,提问作者dexdagr8
相关产品推荐
相关产品推荐

