MongoDb非ISO日期格式的TTL索引



下面是我的示例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类型,如TTL索引文档所述。

如果文档中的索引字段不是日期或保存日期值的数组,则文档将不会过期。

您需要将这些字符串转换为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日期对象,那么查询只拿起"字符串"值进行转换。

理想情况下,您应该删除已经在"Timestamp"字段上的索引,然后在更新后重新创建它们。这消除了将更新的信息写入索引的开销。您还可以在新索引创建的基础上设置一个前景索引,这也将节省索引本身消耗的一些空间。

最新更新