我使用mongo db来存储通知,每天午夜运行cron个作业(job)来挑选旧通知并删除它们.

删除策略具有保留"sourceObjectIdentifier""notificationType"的每个组合的最旧通知的逻辑.将查询1的聚合输出提供给查询2以形成删除查询.

query 1-query 1-

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

query 2-query 2-

{
  "deliveryTime": {
    "$gt": "$datefrom"
  },
  "creationTime": {
    "$lt": "dateto"
  },
  "notificationId": {
    "$nin": [query_1_output]
  }
}

如果集合中的通知数量较少,则此删除逻辑可以很好地工作,但当通知数量在200k或更多时,删除逻辑会花费较长时间.

有人能建议我如何改进查询吗?查询1和查询2可以一起执行吗?

推荐答案

不清楚你是如何定义"最新通知"的.

  • 最近插入的通知是什么?
  • 最棒的notificationId的通知?
  • 最新creationTime的通知?

首先,确保你有一个关于notificationClass的指数.{sourceObjectIdentifier: 1, notificationType: 1}点的组合指数也可能有所帮助.

使用$setWindowFields查找最新通知(排名=1),并删除所有其他通知.下面的命令将"最新通知"视为具有最新creationTime的通知.

var deleteDocs = [];
db.persistentEvent.aggregate([
   { $match: { notificationClass: "category" } },
   {
      $setWindowFields: {
         partitionBy: {
            sourceObjectIdentifier: "sourceObjectIdentifier",
            notificationType: "$notificationType"
         },
         sortBy: { creationTime: -1 },
         output: {
            rank: { $rank: {} },
         }
      }
   },
   { $match: { rank: { $gt: 1 } } },
   { $project: { _id: 1 } }
]).toArray().forEach(doc => {
   deleteDocs.push(doc._id);
   if (deleteDocs.length > 10000) {
      db.persistentEvent.deleteMany({ _id: { $in: deleteDocs } });
      deleteDocs = [];
   }
})
if (deleteDocs.length > 0)
   db.persistentEvent.deleteMany({ _id: { $in: deleteDocs } });

   

Mongo Playground

Mongodb相关问答推荐

MongoDB 4.4如何使用未知密钥更新dict

在MongoDB查询中添加来自另一个集合的匹配文档的计数

MongoDB通过查找具有多个数组的对象进行聚合

MongoDB v4.4聚合的$getfield替代方案

如何联接Mongoose中的集合并检索特定字段

MongoDB:如何获取多个$indexOfArray值?

Spring数据MongoDB(聚合)

如何获取键值对的对象,其中值仅具有 mongoDB 中的投影字段

Mongo查找条件:不存在

mongoose递归填充

在 Nodejs 中配置最大旧空间大小

带有 jQ​​uery Ajax/JSON 前端的 MongoDB 或 CouchDB 中间件

MongoError:Topology is closed, please connect despite established database connection

查询 Mongoid/rails 3 中的嵌入对象(Lower than、Min 运算符和排序)

如何从 Mongoose 模型对象中获取集合名称

Meteor订阅不更新集合的排序顺序

使用命令行从 MongoDB 数据库中的所有集合中删除所有索引

MongoDB mongoexport 查询

如何在 Ubuntu 上安装 mongodb-clients 最新版本?

在 mongodb 集合中查找最旧/最新的帖子