2016-05-07 89 views
1

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

+0

不,这根本不可能。你应该考虑改变你的文件结构。 – styvane

回答

1

在聚合管道中不可能。这里的一般前提是将数字表示转换为字符串等效,然后在循环中进行更新。对于循环,您将需要使用forEach()方法或光标方法next()访问文档的任何手动循环由find()方法返回的光标。

在循环中,首先将字段转换为字符串格式,然后转换为“2016-04-07”等区域设置不敏感的日期格式。一旦你那么格式使用$set运算符,如下面的例子,其中场被称为created_at创建一个新的ISODate对象与和更新的领域,目前持有指定的数字格式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)}} 
    ) 
}; 

为了提高性能,尤其是与大集合打交道时,需要使用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": 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(); } 

下一个例子适用于新的MongoDB版本3.2这已经deprecated the Bulk API,并提供了新的一套使用bulkWrite()的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);