MongoDB聚合管道过滤无type或type为null的目的地并分组订单
调整后的MongoDB聚合管道方案
假设原聚合管道已包含$lookup关联locations集合的步骤,现在需要在$lookup之后、分组之前添加一个$set阶段,用$reduce实现destinations数组的过滤:
{ $set: { destinations: { $reduce: { input: "$destinations", initialValue: [], in: { $cond: [ { $and: [ { $ne: ["$$this.type", null] }, { $exists: ["$$this.type", true] } ] }, { $concatArrays: ["$$value", ["$$this"]] }, "$$value" ] } } } } }
核心逻辑说明
$reduce遍历目标数组,用initialValue初始化空数组存储符合条件的元素- 过滤规则通过
$and组合两个判断:$ne: ["$$this.type", null]:排除type字段为null的项$exists: ["$$this.type", true]:排除完全没有type字段的项
- 符合条件的元素通过
$concatArrays追加到结果数组,不符合则直接保留当前结果数组
完整聚合管道示例(结合原分组逻辑)
以下是包含关联验证、过滤、分组的完整流程:
[ // 关联locations集合,匹配ship_to_id/sold_to_id对应的reference_id { $lookup: { from: "locations", let: { shipToId: "$ship_to_id", soldToId: "$sold_to_id" }, pipeline: [ { $match: { $expr: { $or: [ { $eq: ["$reference_id", "$$shipToId"] }, { $eq: ["$reference_id", "$$soldToId"] } ] } } }, { $project: { reference_id: 1, contact_details: 1 } } ], as: "location_matches" } }, // 验证ship_to_id、sold_to_id与contact_details.ref的匹配关系 { $addFields: { valid_ship_to: { $gt: [ { $size: { $filter: { input: "$location_matches", cond: { $eq: ["$$this.reference_id", "$ship_to_id"] } } } }, 0 ] }, valid_sold_to: { $gt: [ { $size: { $filter: { input: "$location_matches", cond: { $eq: ["$$this.reference_id", "$sold_to_id"] } } } }, 0 ] } } }, // 过滤验证不通过的文档 { $match: { $and: [{ valid_ship_to: true }, { valid_sold_to: true }] } }, // 用$reduce过滤destinations数组 { $set: { destinations: { $reduce: { input: "$destinations", initialValue: [], in: { $cond: [ { $and: [ { $ne: ["$$this.type", null] }, { $exists: ["$$this.type", true] } ] }, { $concatArrays: ["$$value", ["$$this"]] }, "$$value" ] } } } } }, // 按指定字段分组统计 { $group: { _id: { ship_to: "$ship_to", sold_to: "$sold_to", contact_email: "$contact_email" }, orders: { $push: "$$ROOT" }, total_count: { $sum: 1 } } } ]
补充:更简洁的替代方案
如果不限制必须用$reduce,用$filter可以更直观实现过滤:
{ $set: { destinations: { $filter: { input: "$destinations", cond: { $and: [ { $ne: ["$$this.type", null] }, { $exists: ["$$this.type", true] } ] } } } } }
内容的提问来源于stack exchange,提问作者Amaarockz
相关产品推荐
相关产品推荐

