在 mongo 中创建条件 TTL
Create a conditional TTL in mongo
我有一个特定的任务要完成,但我没有找到任何特定的方法来完成它。
假设我有一个用于发送邮件的应用程序。我将这些电子邮件记录在 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' 上创建了一个为期 2 天的 TTL 索引。
但我也不想删除为将来安排的行或请求。
我一直在寻找某种条件 TTL,但找不到任何此类解决方案。
在 MongoDB.
中是否有条件 TTL 或任何其他方法可用?
我想创建一个 TTL,其工作方式如下:
if(requestType!=2 and createdDate < -2days)
delete row;
或者有什么方法可以让我使用任何语言对某些文档进行更改,以免它们过期。
编辑:我解决了这个问题,在预定电子邮件的情况下,scheduledDate
和 createdDate
使用相同的值。
您可以只在scheduledDate
上创建一个TTL索引,如果值为零则不会被删除。根据 documentation,如果文档中的索引字段不是日期或包含日期值的数组,则文档不会过期。
使用 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()
个条目都将被删除,而第一个值为零的记录将保留
我只想添加另一个字段。没有那么多数据:
{
'_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)中,但这些想法应该适用于您正在使用的任何框架:
默认值
您可以将默认值添加到过期字段,值为 'created date + 2 days'。
{
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 以取消自动删除。
唯一需要注意的是,如果您更改预定时间,则需要更新过期字段。
从 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/
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);
我有一个特定的任务要完成,但我没有找到任何特定的方法来完成它。 假设我有一个用于发送邮件的应用程序。我将这些电子邮件记录在 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' 上创建了一个为期 2 天的 TTL 索引。
但我也不想删除为将来安排的行或请求。
我一直在寻找某种条件 TTL,但找不到任何此类解决方案。
在 MongoDB.
中是否有条件 TTL 或任何其他方法可用?我想创建一个 TTL,其工作方式如下:
if(requestType!=2 and createdDate < -2days)
delete row;
或者有什么方法可以让我使用任何语言对某些文档进行更改,以免它们过期。
编辑:我解决了这个问题,在预定电子邮件的情况下,scheduledDate
和 createdDate
使用相同的值。
您可以只在scheduledDate
上创建一个TTL索引,如果值为零则不会被删除。根据 documentation,如果文档中的索引字段不是日期或包含日期值的数组,则文档不会过期。
使用 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()
个条目都将被删除,而第一个值为零的记录将保留
我只想添加另一个字段。没有那么多数据:
{
'_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)中,但这些想法应该适用于您正在使用的任何框架:
默认值
您可以将默认值添加到过期字段,值为 'created date + 2 days'。
{
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 以取消自动删除。
唯一需要注意的是,如果您更改预定时间,则需要更新过期字段。
从 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/
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);