MongoDB聚合查询:lookup后筛选保留无匹配用户数据
MongoDB聚合查询调整方案
问题核心是避免$unwind导致的用户重复,同时保留所有初始筛选的用户,无匹配班次的用户显示shifts: {},有匹配的仅展示指定日期的班次数据。调整思路是将日期过滤逻辑嵌入$lookup的内部管道,而非后续的$match,再处理空数组的情况。
具体聚合表达式
db.users.aggregate([ // 1. 初始用户筛选条件(替换为你的实际过滤规则) { $match: { // 示例:筛选状态为活跃的用户 status: "active" } }, // 2. 关联shifts集合,同时在内部管道过滤日期 { $lookup: { from: "shifts", let: { user_id: "$_id" }, // 假设users的_id与shifts的userId字段关联 pipeline: [ { $match: { $expr: { $and: [ { $eq: ["$userId", "$$user_id"] }, // 用户关联条件 // 替换为你的日期匹配规则,示例:筛选2024年1月的班次 { $gte: ["$date", ISODate("2024-01-01T00:00:00Z")] }, { $lte: ["$date", ISODate("2024-01-31T23:59:59Z")] } ] } } } ], as: "shifts" } }, // 3. 处理shifts字段:空数组转为空对象,非空则保留匹配的班次数据 { $addFields: { shifts: { $cond: { if: { $eq: ["$shifts", []] }, then: {}, // 若希望仅展示单条匹配班次,可替换为 { $arrayElemAt: ["$shifts", 0] } else: "$shifts" } } } } ])
关键调整说明
- 将日期过滤移至
$lookup内部:这样只会关联符合日期条件的班次,避免后续$unwind导致的用户重复,同时保留无匹配班次的用户(此时shifts为空数组)。 - 空数组转空对象:通过
$cond判断shifts是否为空数组,为空则替换为{},满足需求格式。 - 避免
$unwind:若无需拆分班次数组,直接保留数组即可;若仅需单条班次,用$arrayElemAt取数组第一个元素即可,无需$unwind。
内容的提问来源于stack exchange,提问作者chirag prajapati
相关产品推荐
相关产品推荐

