You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.07 03:40:43