文档集合中的日期字段由yyyymmdd格式的整数表示:例如20160407.有没有办法将它作为汇总管道的一部分转换为日期,以便可以用它来按相应的周数对文件进行分组?
答案 0 :(得分:1)
聚合管道中不可能。这里的一般前提是将数字表示转换为其字符串等效,然后在循环中进行更新。对于循环,您需要手动迭代 find()
方法返回的光标,方法是使用 forEach()
方法或光标方法 next()
访问文档。
在循环中,首先将字段转换为字符串格式,然后转换为区域设置不敏感的日期格式,如" 2016-04-07"。获得格式后,使用 $set
运算符创建一个新的ISODate对象,然后使用 Bulk API 运算符更新该字段,如下面的示例,其中字段名为created_at
,当前以指定的数字格式YYYYMMDD:
var cursor = db.collection.find({"created_at": {"$exists": true, "$type": 1 }});
while (cursor.hasNext()) {
var doc = cursor.next(),
dateStr = doc.created_at.toString(),
dateStr.match(/(\d{4})(\d{2})(\d{2})/),
betterDateStr = match[2] + '-' + match[3] + '-' + match[1];
db.collection.update(
{"_id" : doc._id},
{"$set" : {"created_at" : new ISODate(betterDateStr)}}
)
};
为了提高性能,尤其是在处理大型集合时,请利用 deprecated the Bulk API 进行批量更新,因为您将以1000个批量发送操作到服务器您可以获得更好的性能,因为您不是每次请求都向服务器发送一次请求。
以下演示了此方法,第一个示例使用MongoDB版本>= 2.6 and < 3.2
中提供的批量API。它更新所有
通过将created_at
字段更改为日期字段来收集集合中的文档:
var bulk = db.collection.initializeUnorderedBulkOp(),
counter = 0;
db.collection.find({"created_at": {"$exists": true, "$type": 1 }}).forEach(function (doc) {
var dateStr = doc.created_at.toString(),
dateStr.match(/(\d{4})(\d{2})(\d{2})/),
betterDateStr = match[2] + '-' + match[3] + '-' + match[1];
newDate = new ISODate(betterDateStr);
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(); }
下一个示例适用于自 bulkWrite()
以来的新MongoDB版本3.2
,并使用 {{3}} 提供了一套更新的api强>:
var bulkOps = [];
db.collection.find({"created_at": {"$exists": true, "$type": 1 }}).forEach(function (doc) {
var dateStr = doc.created_at.toString(),
dateStr.match(/(\d{4})(\d{2})(\d{2})/),
betterDateStr = match[2] + '-' + match[3] + '-' + match[1];
newDate = new ISODate(betterDateStr);
bulkOps.push(
{
"updateOne": {
"filter": { "_id": doc._id } ,
"update": { "$set": { "created_at": newDate } }
}
}
);
})
db.collection.bulkWrite(bulkOps);