mongodb:将整数转换为日期

时间:2016-05-07 06:54:10

标签: mongodb

文档集合中的日期字段由yyyymmdd格式的整数表示:例如20160407.有没有办法将它作为汇总管道的一部分转换为日期,以便可以用它来按相应的周数对文件进行分组?

1 个答案:

答案 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}}

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);