Mongo聚合String到ISODate

时间:2015-09-06 20:12:22

标签: mongodb mongodb-query aggregation-framework

在一个集合中,我存储了这种文件:

{
    "_id" : ObjectId("55e8a5cba21b9e051eb448d1"),
    "created_at" : "2015-01-01T00:00:24Z",
    ...
}

我想将created_at的类型从String更改为ISODate以获取

{
    "_id" : ObjectId("55e8a5cba21b9e051eb448d1"),
    "created_at" : ISODate("2015-01-01T00:00:24Z)",
    ...
}

我找到了一个解决方案:遍历所有集合

db.trial.find().forEach(
    function(doc) { 
        doc.created_at = ISODate(doc.created_at); 
        db.events_January_watch.save(doc);
    }
);

但这是非常缓慢和低效的,我宁愿使用聚合管道+ $ out

这就是我的尝试:

db.trial.aggregate(
    [
        {
            $project: {
                created_at : "$created_at",                                     
                created_at_iso: {$add: ISODate("$created_at_noTime") }
            }
        },
        {
            $out: "trialIso"
        }
    ],
    {
        allowDiskUse: true
    }
);

哪个抛出: E QUERY错误:ISO日期无效

我不明白为什么,因为

ISODate("2015-01-01T00:00:24Z")

在mongo shell中完美运行。

(这是因为,$ created_at变量尚未在聚合管道中设置?)

1 个答案:

答案 0 :(得分:5)

执行此操作的最佳方法是使用"Bulk"操作

var bulk = db.trial.initializeUnorderedBulkOp(),
    count = 0;

db.trial.find().forEach(function(doc) {
    bulk.find({ "_id": doc._id }).updateOne({
        "$set": { "created_at": ISODate(doc.created_at) }
    })
    count++;
    if (count % 1000 == 0) {
        // Execute per 1000 operations and re-init
        bulk.execute();
        bulk = db.trial.initializeUnorderedBulkOp();
    }
})


if (count % 1000 != 0) 
    bulk.execute();