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

MongoDB:数组对象元素映射与日期条件匹配分组需求

MongoDB 实现跨数组对象的日期差配对分组

问题背景

需要对集合中文档的e_date数组对象与e_date_1数组对象进行年份差计算,当两个对象的日期年份差绝对值≥13时,将这对对象组合成新的数组元素,最终输出所有符合条件的配对结果,而非仅布尔值判断矩阵。

集合示例数据

[
  {
    "_id": ObjectId("60d21b4667d0d8992e610c85"),
    "e_date": [
      { "id": 1, "date": ISODate("2000-05-10") },
      { "id": 2, "date": ISODate("2023-03-15") }
    ],
    "e_date_1": [
      { "id": 101, "date": ISODate("1985-07-20") },
      { "id": 102, "date": ISODate("2010-11-01") }
    ]
  }
]

现有代码的局限

当前使用嵌套$map仅能生成布尔判断矩阵,无法保留实际配对的对象信息:

db.collection.aggregate([
  {
    $project: {
      pair_check: {
        $map: {
          input: "$e_date",
          as: "ed",
          in: {
            $map: {
              input: "$e_date_1",
              as: "ed1",
              in: {
                $gte: [
                  { $abs: { $subtract: [{ $year: "$$ed.date" }, { $year: "$$ed1.date" }] } },
                  13
                ]
              }
            }
          }
        }
      }
    }
  }
])

输出为布尔矩阵:

{
  "_id": ObjectId("60d21b4667d0d8992e610c85"),
  "pair_check": [[true, false], [false, true]]
}

解决方案:生成实际配对对象数组

可以通过两种方式实现,根据数据规模选择合适的方案:

方案1:使用$unwind+$group(适合数据量中等的场景)

通过展开两个数组,筛选符合条件的配对后重新分组:

db.collection.aggregate([
  // 展开e_date数组
  { $unwind: "$e_date" },
  // 展开e_date_1数组
  { $unwind: "$e_date_1" },
  // 计算年份差并标记符合条件的配对
  {
    $addFields: {
      is_valid: {
        $gte: [
          { $abs: { $subtract: [{ $year: "$e_date.date" }, { $year: "$e_date_1.date" }] } },
          13
        ]
      }
    }
  },
  // 筛选出符合条件的配对
  { $match: { is_valid: true } },
  // 按原文档_id分组,收集所有有效配对
  {
    $group: {
      _id: "$_id",
      valid_pairs: {
        $push: {
          e_date_obj: "$e_date",
          e_date_1_obj: "$e_date_1"
        }
      }
    }
  }
])

方案2:使用$reduce+$filter(适合避免文档展开的场景)

在$project阶段直接通过嵌套聚合操作生成配对数组,无需展开文档:

db.collection.aggregate([
  {
    $project: {
      valid_pairs: {
        $reduce: {
          input: "$e_date",
          initialValue: [],
          in: {
            // 拼接当前e_date元素匹配到的所有e_date_1元素
            $concatArrays: [
              "$$value",
              {
                $map: {
                  // 过滤出与当前e_date元素年份差≥13的e_date_1元素
                  input: {
                    $filter: {
                      input: "$e_date_1",
                      as: "ed1",
                      cond: {
                        $gte: [
                          { $abs: { $subtract: [{ $year: "$$this.date" }, { $year: "$$ed1.date" }] } },
                          13
                        ]
                      }
                    }
                  },
                  as: "matched_ed1",
                  // 生成配对对象
                  in: {
                    e_date_obj: "$$this",
                    e_date_1_obj: "$$matched_ed1"
                  }
                }
              }
            ]
          }
        }
      }
    }
  }
])

期望输出

两种方案均会输出如下结构的结果:

{
  "_id": ObjectId("60d21b4667d0d8992e610c85"),
  "valid_pairs": [
    {
      "e_date_obj": { "id": 1, "date": ISODate("2000-05-10") },
      "e_date_1_obj": { "id": 101, "date": ISODate("1985-07-20") }
    },
    {
      "e_date_obj": { "id": 2, "date": ISODate("2023-03-15") },
      "e_date_1_obj": { "id": 101, "date": ISODate("1985-07-20") }
    }
  ]
}

内容的提问来源于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.06 16:05:42