使用 MongoDB 4.0 及更新版本
$toDate 运算符会将值转换为日期。如果该值无法转换为日期,则会出现 $toDate 错误。如果值为 null 或缺失,$toDate 返回 null:
您可以在聚合管道中使用它,如下所示:
db.collection.aggregate([
{ "$addFields": {
"created_at": {
"$toDate": "$created_at"
}
} }
])
以上等价于使用$convert运算符如下:
db.collection.aggregate([
{ "$addFields": {
"created_at": {
"$convert": {
"input": "$created_at",
"to": "date"
}
}
} }
])
使用 MongoDB 3.6 及更新版本
您还可以使用 $dateFromString 运算符将日期/时间字符串转换为日期对象,并具有指定日期格式和时区的选项:
db.collection.aggregate([
{ "$addFields": {
"created_at": {
"$dateFromString": {
"dateString": "$created_at",
"format": "%m-%d-%Y" /* <-- option available only in version 4.0. and newer */
}
}
} }
])
使用 MongoDB 版本>= 2.6 and < 3.2
如果 MongoDB 版本没有进行转换的本地运算符,您需要手动迭代 find() 方法返回的游标,方法是使用 forEach() 方法
或游标方法 next() 来访问文档。使用循环,将字段转换为 ISODate 对象,然后使用 $set 运算符更新字段,如下例所示,其中字段名为 created_at,当前保存字符串中的日期格式:
var cursor = db.collection.find({"created_at": {"$exists": true, "$type": 2 }});
while (cursor.hasNext()) {
var doc = cursor.next();
db.collection.update(
{"_id" : doc._id},
{"$set" : {"created_at" : new ISODate(doc.created_at)}}
)
};
为了提高性能,尤其是在处理大型集合时,请利用 Bulk API 进行批量更新,因为您将以 1000 个批量将操作发送到服务器,从而为您提供更好的性能,因为您不会将每个请求都发送到服务器,每 1000 个请求中只发送一次。
下面演示了这种方法,第一个示例使用了 MongoDB 版本>= 2.6 and < 3.2 中可用的 Bulk API。它更新所有
通过将 created_at 字段更改为日期字段来获取集合中的文档:
var bulk = db.collection.initializeUnorderedBulkOp(),
counter = 0;
db.collection.find({"created_at": {"$exists": true, "$type": 2 }}).forEach(function (doc) {
var newDate = new ISODate(doc.created_at);
bulk.find({ "_id": doc._id }).updateOne({
"$set": { "created_at": newDate}
});
counter++;
if (counter % 1000 == 0) {
bulk.execute(); // Execute per 1000 operations and re-initialize every 1000 update statements
bulk = db.collection.initializeUnorderedBulkOp();
}
})
// Clean up remaining operations in queue
if (counter % 1000 != 0) { bulk.execute(); }
使用 MongoDB 3.2
下一个示例适用于自 deprecated the Bulk API 以来的新 MongoDB 版本 3.2,并使用 bulkWrite() 提供了一组更新的 api:
var bulkOps = [],
cursor = db.collection.find({"created_at": {"$exists": true, "$type": 2 }});
cursor.forEach(function (doc) {
var newDate = new ISODate(doc.created_at);
bulkOps.push(
{
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "created_at": newDate } }
}
}
);
if (bulkOps.length === 500) {
db.collection.bulkWrite(bulkOps);
bulkOps = [];
}
});
if (bulkOps.length > 0) db.collection.bulkWrite(bulkOps);