在 mongo 中创建一个条件 TTL


我想

完成一项特定的任务,但我没有找到任何特定的方法来做到这一点。假设我有一个用于发送邮件的应用程序。我在 mongo 的一个集合中记录了这些电子邮件。使用此应用程序,我可以立即发送邮件,也可以为将来安排电子邮件。集合中文档的结构如下:

{
'_id' : 123456789,
'to_email' : 'xyz@gmail.com'
'from_email' : 'abc@gmail.com'
'subject': 'some subject'
'type' : '<1 if normal and 2 if scheduled>',
'createdDate' '<date when mail was sent or the request was created>',
'scheduledDate' : '<time for which mail is scheduled>'
.. and many more key-value pairs
}

scheduledDate字段可以是零或任何日期,具体取决于是否计划。我不想保留超过 2 天的数据,所以我在"createdDate"上创建了一个 TTL 索引,为期 2 天。但我也不想删除计划在未来的行或请求。我正在寻找某种有条件的TTL,但找不到任何这样的解决方案。

是否有任何可用的方法,例如条件TTL或任何其他方法可以在MongoDB中执行此操作。

我想创建一个工作方式如下的 TTL:

if(requestType!=2 and createdDate < -2days)
delete row;

或者有没有办法让我使用任何语言对某些文档进行更改,以免它们过期。

编辑:我解决了这个问题,在预定电子邮件的情况下,对scheduledDatecreatedDate使用相同的值。

从MongoDB 3.2开始,还可以使用指定的过滤器表达式添加部分TTL索引。如果您只需要删除普通的未计划的电子邮件,则可以使用以下方法:

db.email.createIndex( {createdDate: 1}, {
    expireAfterSeconds: 172800, // 2 days
    partialFilterExpression: {
        scheduledDate: 0
    }
});

请注意,partialFilterExpression对可能的筛选条件有限制:https://docs.mongodb.com/manual/core/index-partial/

我只想添加另一个字段。这不是那么多数据:

{
'_id' : 123456789,
'createdDate' '<date when mail was sent or the request was created>',
'scheduledDate' : '<time for which mail is scheduled>'
'expires': '<Date or NULL>'
}

将 0 秒的 TTL 索引添加到过期字段。不要将 TTL 添加到其他日期。

下面的例子在Mongoose(Node的ORM(中,但这些想法应该延续到你正在使用的任何框架中:

默认值

您可以在过期字段中添加一个默认值,值为"创建日期 + 2 天"。

{
  type: Date,
  default: function() { 
    return new Date(Date.now() + 1000*60*60*24*2);
  }
}

计划任务的不同到期日期

只需明确设置日期:

myNewDocument.expires = new Date( scheduled + ... );

或者更改设置默认值的函数:

function() {
    if(this.get("type") === 2) {
      return scheduled_date_plus_2_days;
    } else {
      return created_date_plus_2_days;
    }
}

完全没有到期

将字段设置为 NULL:

myNewDocument.expires = null;

这样,您就可以为普通电子邮件,重要电子邮件,预定电子邮件等选择不同的到期时间。如果您准时,甚至可以将expires字段设置为 NULL 以取消自动删除。
唯一需要注意的是,如果您更改计划的时间,则需要更新过期字段。

您可以在 scheduledDate 上创建一个 TTL 索引,如果值为零,则不会删除。根据文档,如果文档中的索引字段不是日期或包含日期值的数组,则文档不会过期。

使用 Mongo 3.2,我已经使用此测试集合验证了这种情况:

db.data.drop()
db.data.save({scheduledDate: 0})
db.data.save({scheduledDate: new Date()})
db.data.save({scheduledDate: new Date()})
db.data.createIndex( { "scheduledDate": 1 }, { expireAfterSeconds:1} )

使用此集合时,所有new Date()条目都将被删除,而第一个值为零的记录保持不变

const mongoose = require("mongoose");
const Schema = mongoose.Schema;
let PassWordReSate = new Schema(
  {
    hex: String,
    email: String,
  },
  {
    collection: "PassWordReSate",
    timestamps: true,
  }
);
PassWordReSate.path("createdAt").index({ expires: 6 });
module.exports = mongoose.model("PassWordReSate", PassWordReSate);

最新更新