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

MongoDB基于xCorrelationId查重复数据:modifiedBy匹配最大modifiedDate问题

问题解决:MongoDB聚合关联maxModifiedDate对应的modifiedBy字段

需求背景

需要在MongoDB的audit集合中,基于xCorrelationId字段识别重复数据,现有聚合已实现统计重复数、合并events、获取最小creationDate和最大modifiedDate,但无法让modifiedBy字段对应拥有最大modifiedDate的记录。

集合样例数据

[
  {
    "_id": ObjectId("60d21b4667d0d8992e610c85"),
    "xCorrelationId": "CORR-123",
    "events": ["CREATE"],
    "creationDate": ISODate("2021-06-23T10:00:00Z"),
    "modifiedDate": ISODate("2021-06-23T10:00:00Z"),
    "modifiedBy": "user1"
  },
  {
    "_id": ObjectId("60d21b4667d0d8992e610c86"),
    "xCorrelationId": "CORR-123",
    "events": ["UPDATE"],
    "creationDate": ISODate("2021-06-23T10:00:00Z"),
    "modifiedDate": ISODate("2021-06-23T10:30:00Z"),
    "modifiedBy": "user2"
  },
  {
    "_id": ObjectId("60d21b4667d0d8992e610c87"),
    "xCorrelationId": "CORR-456",
    "events": ["CREATE"],
    "creationDate": ISODate("2021-06-24T09:00:00Z"),
    "modifiedDate": ISODate("2021-06-24T09:00:00Z"),
    "modifiedBy": "user3"
  }
]

现有聚合查询(问题版)

db.audit.aggregate([
  {
    $group: {
      _id: "$xCorrelationId",
      count: { $sum: 1 },
      mergedEvents: { $addToSet: "$events" },
      minCreationDate: { $min: "$creationDate" },
      maxModifiedDate: { $max: "$modifiedDate" },
      // 此处modifiedBy为随机取的第一条,不对应maxModifiedDate
      modifiedBy: { $first: "$modifiedBy" }
    }
  },
  { $match: { count: { $gt: 1 } } }
])

期望输出

[
  {
    "_id": "CORR-123",
    "count": 2,
    "mergedEvents": [["CREATE"], ["UPDATE"]],
    "minCreationDate": ISODate("2021-06-23T10:00:00Z"),
    "maxModifiedDate": ISODate("2021-06-23T10:30:00Z"),
    "modifiedBy": "user2" // 对应最大modifiedDate的记录的modifiedBy
  }
]

解决方案:两种MongoDB聚合实现方式

方式一:预排序后分组(高效推荐)

利用排序+$last操作符,确保同一xCorrelationId组内最后一条记录就是modifiedDate最大的记录,直接取其modifiedBy:

db.audit.aggregate([
  // 按xCorrelationId分组前,先按xCorrelationId+modifiedDate升序排序
  // 若有索引{xCorrelationId:1, modifiedDate:1},此步骤性能最优
  { $sort: { xCorrelationId: 1, modifiedDate: 1 } },
  {
    $group: {
      _id: "$xCorrelationId",
      count: { $sum: 1 },
      mergedEvents: { $addToSet: "$events" },
      minCreationDate: { $min: "$creationDate" },
      maxModifiedDate: { $last: "$modifiedDate" },
      modifiedBy: { $last: "$modifiedBy" }
    }
  },
  { $match: { count: { $gt: 1 } } }
])

方式二:分组后筛选匹配(无需预排序)

通过分组收集所有modifiedDate与modifiedBy的组合,再筛选出对应最大modifiedDate的modifiedBy:

db.audit.aggregate([
  {
    $group: {
      _id: "$xCorrelationId",
      count: { $sum: 1 },
      mergedEvents: { $addToSet: "$events" },
      minCreationDate: { $min: "$creationDate" },
      // 收集所有modifiedDate和modifiedBy的关联记录
      modifiedPairs: {
        $push: {
          date: "$modifiedDate",
          by: "$modifiedBy"
        }
      }
    }
  },
  { $match: { count: { $gt: 1 } } },
  {
    $addFields: {
      maxModifiedDate: { $max: "$modifiedPairs.date" },
      // 筛选出date等于maxModifiedDate的记录,提取对应的modifiedBy
      modifiedBy: {
        $first: {
          $map: {
            input: {
              $filter: {
                input: "$modifiedPairs",
                cond: { $eq: ["$$this.date", { $max: "$modifiedPairs.date" }] }
              }
            },
            as: "pair",
            in: "$$pair.by"
          }
        }
      }
    }
  },
  // 移除临时字段modifiedPairs
  { $project: { modifiedPairs: 0 } }
])

方案对比

  • 方式一:性能更优,尤其适合大数据量场景,若存在复合索引可避免全表排序。
  • 方式二:无需预排序,逻辑直观,适合数据量较小或无法创建索引的场景。

内容的提问来源于stack exchange,提问作者Poonam Gupta

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.17 21:40:39