非ISO日期格式的MongoDb TTL索引

时间:2015-09-03 18:52:21

标签: mongodb mongodb-query ttl

以下是我的示例Json消息,它的时间戳格式为YYYY-MM-DDThh:mmTZD(例如2015-08-18T22:43:01-04:00)

此外,我有30天的TTL索引设置,但我的数据没有被删除。我知道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

1 个答案:

答案 0 :(得分:3)

为了使TTL清理过程能够使用定义的TTL索引,指定的字段必须包含Date BSON类型,对于TTL索引,covered in the documentation也是如此

  

如果文档中的索引字段不是date或包含日期值的数组,则文档不会过期。

您需要将此类字符串转换为BSON日期。这也是明智之举,因为BSON Date的内部存储是一个数字时间戳值,这比字符串占用的存储空间少得多。

转换需要更新" cast"到一个约会对象。作为一个"一个关闭"这可能最好通过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,这也将节省索引本身消耗的空间。