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

MongoDB通知清理查询优化及多查询合并执行咨询

优化方案与合并查询实现

1. 先创建高性能复合索引

大数据量下索引是核心优化点,创建以下复合索引,覆盖查询的过滤、分组、排序全场景,避免全表扫描:

db.persistentEvent.createIndex({
  notificationClass: 1,
  sourceObjectIdentifier: 1,
  notificationType: 1,
  creationTime: 1,
  deliveryTime: 1
})

2. 修正分组逻辑,正确获取需保留的通知ID

原查询的$sort阶段放在$project之后,因$project已丢弃sourceObjectIdentifier和creationTime字段,排序完全无效。且要保留最早通知,需先按creationTime升序排序,再分组取每组第一条数据的ID:

db.persistentEvent.aggregate([
  { "$match": { "notificationClass": "category" } },
  { "$sort": {
    "sourceObjectIdentifier": 1,
    "notificationType": 1,
    "creationTime": 1
  } },
  { "$group": {
    "_id": {
      "sourceObjectIdentifier": "$sourceObjectIdentifier",
      "notificationType": "$notificationType"
    },
    "keepNotificationId": { "$first": "$notificationId" }
  } },
  { "$project": { "_id": 0, "keepNotificationId": 1 } }
])

3. 合并查询为单步删除(无需分两次执行)

MongoDB 4.2及以上版本支持用聚合管道作为deleteMany的过滤条件,直接在数据库层面完成筛选+删除操作,避免将大量ID拉取到客户端执行$nin(这是大数据量下耗时的核心原因)。

高效合并删除命令

// 替换为你的实际时间变量
const dateFrom = ISODate("2024-01-01T00:00:00Z");
const dateTo = ISODate("2024-06-01T00:00:00Z");

db.persistentEvent.deleteMany([
  // 基础过滤条件
  { "$match": {
    "notificationClass": "category",
    "deliveryTime": { "$gt": dateFrom },
    "creationTime": { "$lt": dateTo }
  } },
  // 关联同组文档,获取组内最早的通知ID
  { "$lookup": {
    "from": "persistentEvent",
    "let": {
      "sourceId": "$sourceObjectIdentifier",
      "type": "$notificationType"
    },
    "pipeline": [
      { "$match": {
        "$expr": {
          "$and": [
            { "$eq": ["$sourceObjectIdentifier", "$$sourceId"] },
            { "$eq": ["$notificationType", "$$type"] },
            { "$eq": ["$notificationClass", "category"] }
          ]
        }
      } },
      { "$sort": { "creationTime": 1 } },
      { "$limit": 1 },
      { "$project": { "_id": 0, "notificationId": 1 } }
    ],
    "as": "groupEarliest"
  } },
  // 筛选出不属于组内最早的文档
  { "$match": {
    "$expr": { "$ne": ["$notificationId", { "$arrayElemAt": ["$groupEarliest.notificationId", 0] }] }
  } }
])

额外优化建议

  • 若notificationId就是文档的_id,直接用_id替代,减少字段存储和查询开销
  • 若每日删除数据量极大,可分批删除(比如每次删1000条),避免长时间锁表
  • 定期清理无效索引,保证索引使用效率

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 18:23:16