2014-09-22 46 views
9

我有一個文檔集合,其中有一個已知值爲數字的值,但存儲爲字符串。改變字段的類型不在我的控制範圍之內,但我想在聚合中使用該字段(比如,將其平均)。將字符串轉換爲MongoDB投影中的數字

看來我應該在分組之前使用投影,並在該投影中根據需要轉換字段。我似乎無法得到恰到好處的語法 - 我所嘗試的任何一種方法都給了我NaN,或者新的字段在聚合的下一步中完全沒有了。

$project: { 
    value: '$value', 
    valueasnumber: ???? 
} 

鑑於上述非常簡單的例子,其中$值的所有文檔中的內容是字符串類型,而是將解析到一個號碼,我該怎麼辦,使valueasnumber一個新的(不存在)字段它的解析版本是$ value的類型是double嗎?

我試着像下面的例子(和十幾個類似的東西)的東西:

{ $add: new Number('$value').valueOf() } 
new Number('$value').valueOf() 

難道我完全找錯了樹?任何幫助將不勝感激!

(要100%清楚,以下是我想如何使用新字段)。

$group { 
    score: { 
     $avg: '$valueasnumber' 
    } 
} 
+1

從MongoDB 2.6開始,你倒黴了。聚合框架中沒有可用的數字解析選項。如果該字段代表一個數字,它應該確實存儲爲一個數字;也許你可以添加另一個字段,這是數字的數字形式?你也可以考慮map/reduce。 – wdberkeley 2014-09-23 14:33:17

+0

感謝大家的評論。我正在嘗試兩種方法,以瞭解最佳效果。看起來,聚合框架比map/reduce有更好的性能,因此可能值得維護第二個字段(作爲數字),以便按預期使用聚合。 – 2014-09-24 13:05:05

+0

可能重複的[如何將字符串轉換爲mongodb中的數值](http://stackoverflow.com/questions/29487351/how-to-convert-string-to-numerical-values-in-mongodb) – styvane 2016-12-29 16:44:25

回答

3

之一,我可以想到的方法是使用一個蒙戈殼的javascript通過添加新的號碼字段,valuesasnumber現有的文檔中(現有的字符串的數目變​​換「值」字段)或修改的文件在新的文檔中。然後使用此數字字段進行進一步計算。

db.numbertest.find().forEach(function(doc) { 
    doc.valueasnumber = new NumberInt(doc.value); 
    db.numbertest.save(doc); 
}); 

使用valueasnumber字段數值計算

db.numbertest.aggregate([{$group : 
    {_id : null, 
    "score" : {$avg : "$valueasnumber"} 
    } 
}]); 
2

核心操作是從值字符串轉換至其不能在aggregate pipeline operation處理當前數。
mapReduce是下面的替代方案。

db.c.mapReduce(function() { 
    emit(this.groupId, {score: Number(this.value), count: 1}); 
}, function(key, values) { 
    var score = 0, count = 0; 
    for (var i = 0; i < values.length; i++) { 
     score += values[i].score; 
     count += values[i].count; 
    } 
    return {score: score, count: count}; 
}, {finalize: function(key, value) { 
    return {score: value.score/value.count}; 
}, out: {inline: 1}});