2016-05-07 88 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);