下面是我的示例 Json 消息,它的时间戳格式为 YYYY-MM-DDThh:mmTZD (例如 2015-08-18T22:43:01-04:00)
此外,我的 TTL 索引设置为 30 天,但我的数据并未被删除。我知道 Mongodb 使用 ISODate("2015-09-03T14:21:30.177-04:00") 类型的格式,但这绝对有必要吗?我可以在索引中进行哪些修改才能使 TTL 正常工作。
我们在多个集合下拥有数百万个文档,并且时不时就会出现空间不足的情况。
JSON:
{
"_id" : ObjectId("55d3ed35817f4809e14e2"),
"AuditEnvelope" : {
"TrackingInformation" : {
"CorelationId" : "2703-4ce2-af68-47832462",
"Timestamp" : "2015-08-18T22:43:01-04:00",
"LogData" : {
"msgDetailJson" : "[Somedata here]"
}
}
}
}
索引
"1" : {
"v" : 1,
"key" : {
"AuditEnvelope.TrackingInformation.Timestamp" : 1
},
"name" : "TTL",
"ns" : "MyDB.MyColl",
"expireAfterSeconds" : 2592000
},
MongoDB 版本:3.0.1
最佳答案
为了使 TTL 清理过程能够使用定义的 TTL 索引,指定字段必须包含 Date
BSON类型,如 covered in the documentation对于 TTL 索引。
If the indexed field in a document is not a date or an array that holds a date value(s), the document will not expire.
您需要将此类字符串转换为 BSON 日期。这也是明智的做法,因为 BSON Date 的内部存储是数字时间戳值,这比字符串占用的存储少得多。
转换需要更新以“转换”为日期对象。作为“一次性”操作,这可能最好通过 MongoDB shell 并使用 Bulk Operations 来完成。以最大限度地减少写回数据时的网络开销。
var bulk = db.MyColl.initializeOrderedBulkOp(),
count = 0;
db.MyColl.find({
"AuditEnvelope.TrackingInformation.Timestamp": { "$type": 2 }
}).forEach(function(doc) {
bulk.find({ "_id": doc._id }).updateOne({
"$set": {
"AuditEnvelope.TrackingInformation.Timestamp":
new Date(doc.AuditEnvelope.TrackingInformation.Timestamp)
}
});
count++;
if ( count % 1000 == 0 ) {
bulk.execute();
bulk = db.MyColl.initializeOrderedBulkOp();
}
});
if ( count % 1000 != 0 )
bulk.execute();
也不是 BSON $type
那里的操作旨在匹配“字符串”,因此即使您开始转换或更改一些代码以开始在字段中生成 BSON 日期对象,查询也只会选取“字符串”值进行转换。
理想情况下,您应该删除“时间戳”字段上已有的索引,然后在更新后重新创建它们。这消除了使用更新信息写入索引的开销。您还可以设置foreground index build在创建新索引时,这也将节省索引本身消耗的一些空间。
关于非 ISO 日期格式的 MongoDb TTL 索引,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32383344/