关于mongodb:Mongo聚合字符串转换为ISODate

Mongo aggregation String to ISODate

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

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

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

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

我找到了一种解决方案:遍历所有集合,进行

1
2
3
4
5
6
db.trial.find().forEach(
    function(doc) {
        doc.created_at = ISODate(doc.created_at);
        db.events_January_watch.save(doc);
    }
);

但是这非常慢且效率低下,我更喜欢使用聚合管道$ out

这是我尝试的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
db.trial.aggregate(
    [
        {
            $project: {
                created_at :"$created_at",                                    
                created_at_iso: {$add: ISODate("$created_at_noTime") }
            }
        },
        {
            $out:"trialIso"
        }
    ],
    {
        allowDiskUse: true
    }
);

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

我不明白为什么

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

在mongo shell中完美运行。

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


做到这一点的最佳方法是使用"批量"操作

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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();