如何在MongoDB中按p_id分组并筛选e_date1 < e_date的文档
解决MongoDB按p_id分组并保留e_date1 < e_date文档的问题
你的需求核心是跨文档比较同一p_id下的e_date和e_date1字段,但单个文档只包含其中一个字段,所以直接用$group按条件分组的思路行不通——因为单文档里没法同时拿到两个字段做比较。下面给出两种贴合需求的解决方案:
方案1:保留符合条件的单个文档
如果你想保留:
- 所有带e_date的文档(可选)
- 带e_date1且其日期小于同p_id下任意一个e_date的文档
可以用以下聚合管道:
db.collection.aggregate([ // 按p_id分组,收集所有e_date和全部文档 { $group: { _id: "$p_id", e_dates: { $push: "$e_date" }, all_docs: { $push: "$$ROOT" } } }, // 筛选符合条件的文档 { $project: { valid_docs: { $filter: { input: "$all_docs", as: "doc", cond: { $or: [ // 保留带e_date的文档(不需要的话可删除此条件) { $ne: ["$$doc.e_date", undefined] }, // 保留e_date1 < 任意e_date的文档 { $and: [ { $ne: ["$$doc.e_date1", undefined] }, { $anyElementTrue: { $map: { input: "$e_dates", as: "ed", cond: { $lt: ["$$doc.e_date1", "$$ed"] } } } } ] } ] } } } } }, // 展开数组为单个文档(可选) { $unwind: "$valid_docs" }, // 恢复原文档结构(可选) { $replaceRoot: { newRoot: "$valid_docs" } } ])
方案2:生成符合条件的文档配对
如果你想得到同p_id下,e_date1文档与e_date文档的配对(仅保留e_date1 < e_date的组合),可以用这个管道:
db.collection.aggregate([ // 按p_id分组,分离e_date和e_date1文档 { $group: { _id: "$p_id", e_date_docs: { $push: { $cond: [{ $ne: ["$e_date", undefined] }, "$$ROOT", null] } }, e_date1_docs: { $push: { $cond: [{ $ne: ["$e_date1", undefined] }, "$$ROOT", null] } } } }, // 过滤掉数组中的空值 { $project: { e_date_docs: { $filter: { input: "$e_date_docs", cond: { $ne: ["$$this", null] } } }, e_date1_docs: { $filter: { input: "$e_date1_docs", cond: { $ne: ["$$this", null] } } } } }, // 生成所有可能的文档配对 { $unwind: "$e_date_docs" }, { $unwind: "$e_date1_docs" }, // 筛选e_date1 < e_date的配对 { $match: { $expr: { $lt: ["$e_date1_docs.e_date1", "$e_date_docs.e_date"] } } }, // 整理输出格式 { $project: { _id: 0, p_id: "$_id", e_date_record: "$e_date_docs", e_date1_record: "$e_date1_docs" } } ])
为什么你的原操作无效?
你之前的$group中,每个文档只包含e_date或e_date1,单文档内无法完成$e_date1 < $e_date的判断——当文档只有e_date时,$e_date1是未定义值,$lt判断返回false;当文档只有e_date1时,$e_date未定义,同样无法得到正确结果。必须先把同一p_id下的所有日期聚合,再做跨文档的条件筛选。
内容的提问来源于stack exchange,提问作者Will Jue
相关产品推荐
相关产品推荐

