将字符串转换为MongoDB投影中的数字

时间:2014-09-22 21:15:43

标签: mongodb mongodb-query

我有一组文档,其值已知为数字,但存储为字符串。更改字段的类型是我无法控制的,但我想在聚合中使用该字段(例如,对其进行平均)。

似乎我应该在分组之前使用投影,并且在该投影中根据需要转换字段。我似乎无法正确地使用语法 - 我尝试的所有内容都给了我NaN,或者在聚合的下一步中忽略了新字段。

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

鉴于上面非常简单的示例,其中所有文档中$ value的内容都是字符串类型,但是将解析为一个数字,我该怎么做才能使valueasnumber为double类型的新(不存在)字段使用解析后的$ value版本?

我尝试过以下示例(以及大约十几个类似的事情):

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

我是否完全吠叫了错误的树?任何帮助将不胜感激!

(要100%明确,以下是我想使用新字段的方式)。

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

3 个答案:

答案 0 :(得分:3)

我能想到的一种方法是使用mongo shell javascript通过在现有文档或新文档中添加新的数字字段,valuesasnumber(现有字符串'value'字段的数字转换)来修改文档。然后使用此数字字段进行进一步计算。

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"}
   }
}]);

答案 1 :(得分: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}});

答案 2 :(得分:1)

现在聚合中有$ toInt转换运算符,您可以检查: https://jira.mongodb.org/browse/SERVER-11400