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

MongoDB重复文档删除需求:基于med、Time、Date字段去重

移除药品列表中的重复MongoDB文档

问题背景

服务器运行的调度程序每日生成未签到药品列表,偶尔会出现重复条目。需要编写脚本检测并删除重复项,匹配med、Time字段(注:示例中Date仅毫秒部分存在差异,视为重复项),每组重复项仅保留一份文档。

示例数据

[
  {
    "_id": ObjectId("6375ea026a0b4e0015d80f77"),
    "med": ObjectId("610845e7f5b0e00017754d50"),
    "Time": "8:00am",
    "Date": "2022-11-16T08:00:00.008+0000"
  },
  {
    "_id": ObjectId("6375ea026a0b4e0015d80fd4"),
    "med": ObjectId("61f988e82cf5760018113cee"),
    "Time": "7:00am",
    "Date": "2022-11-16T08:00:00.008+0000"
  },
  {
    "_id": ObjectId("6375ea026a0b4e0015d80fdd"),
    "med": ObjectId("62d1c6e93603ed00177812ee"),
    "Time": "6:00am",
    "Date": "2022-11-16T08:00:00.008+0000"
  },
  {
    "_id": ObjectId("6375ea02304a870015dfa2ec"),
    "med": ObjectId("610845e7f5b0e00017754d50"),
    "Time": "8:00am",
    "Date": "2022-11-16T08:00:00.005+0000"
  },
  {
    "_id": ObjectId("6375ea02304a870015dfa349"),
    "med": ObjectId("61f988e82cf5760018113cee"),
    "Time": "7:00am",
    "Date": "2022-11-16T08:00:00.005+0000"
  },
  {
    "_id": ObjectId("6375ea02304a870015dfa352"),
    "med": ObjectId("62d1c6e93603ed00177812ee"),
    "Time": "6:00am",
    "Date": "2022-11-16T08:00:00.005+0000"
  }
]

预期输出

[
  {
    "med": ObjectId("610845e7f5b0e00017754d50"),
    "Time": "8:00am",
    "Date": "2022-11-16T08:00:00.008+0000"
  },
  {
    "med": ObjectId("61f988e82cf5760018113cee"),
    "Time": "7:00am",
    "Date": "2022-11-16T08:00:00.008+0000"
  },
  {
    "med": ObjectId("62d1c6e93603ed00177812ee"),
    "Time": "6:00am",
    "Date": "2022-11-16T08:00:00.008+0000"
  }
]

解决方案

1. 聚合查询获取去重结果

如果只需要查询去重后的列表,可使用MongoDB聚合管道:

db.collection.aggregate([
  // 按med和Time分组,保留第一个匹配的文档
  {
    $group: {
      _id: {
        med: "$med",
        Time: "$Time"
      },
      doc: { $first: "$$ROOT" }
    }
  },
  // 提取文档内容,移除分组用的_id
  {
    $replaceRoot: { newRoot: "$doc" }
  },
  // 可选:移除_id字段(如果不需要)
  {
    $project: { _id: 0 }
  }
])

2. 删除重复项的脚本

如果需要直接从集合中删除重复文档,保留每组的第一个文档,可使用以下脚本:

// 先分组获取每组需要保留的文档_id
const duplicates = await db.collection.aggregate([
  {
    $group: {
      _id: { med: "$med", Time: "$Time" },
      duplicateIds: { $push: "$_id" },
      count: { $sum: 1 }
    }
  },
  {
    $match: { count: { $gt: 1 } }
  }
]).toArray();

// 遍历每组,删除除第一个之外的重复文档
for (const group of duplicates) {
  // 移除第一个_id,剩下的都是要删除的
  group.duplicateIds.shift();
  await db.collection.deleteMany({ _id: { $in: group.duplicateIds } });
}

说明

  • 分组依据选择med和Time是因为示例中Date仅毫秒差异,属于调度程序生成的微小误差,视为重复项;如果需要严格匹配Date(包括毫秒),可将Date加入_id的分组字段中。
  • $first操作符会保留每组中最先被查询到的文档,若需要保留最新的文档,可先按Date或_id排序,再使用$last操作符。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.11 21:55:20