Mongo聚合String到ISODate

Max*_*Max 4 mongodb mongodb-query aggregation-framework

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

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

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

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

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

db.trial.find().forEach(
    function(doc) { 
        doc.created_at = ISODate(doc.created_at); 
        db.events_January_watch.save(doc);
    }
);
Run Code Online (Sandbox Code Playgroud)

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

这是我试过的:

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

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

我不明白为什么

ISODate("2015-01-01T00:00:24Z")
Run Code Online (Sandbox Code Playgroud)

在mongo shell中完美运行.

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

sty*_*ane 5

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

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();
Run Code Online (Sandbox Code Playgroud)