首页 > 解决方案 > 重写聚合以映射mongo中的reduce方法

问题描述

我有数据库:

{
    "_id" : ObjectId("5e750506cb670d8afe8c94da"),
    "height" : "166.27",
    "weight" : "68.62",
    "nationality" : "Afghanistan"
    (more fields)
},
{
    "_id" : ObjectId("5e750506cb670d8afe8c99d5"),
    "height" : "162.44",
    "weight" : "71.8",
    "nationality" : "Afghanistan"
(more fields)
}
...

我首先创建了一些聚合:

db.getCollection('people').aggregate([{
$project:
    {
        "nationality": "$nationality",
        "weight": "$weight",
        "height": "$height",
        "bmi": {$divide: [{"$toDouble": "$weight"}, {$pow: [{$divide: [{"$toDouble": "$height"}, 100]},2]}]}
    }
},
{
    $group:
    {
        _id: "$nationality",
        "weight": {$sum:{"$toDouble": "$weight"}},
        "height": {$sum:{"$toDouble": "$height"}},
        "avgbmi": {$avg: "$bmi"},
        "sumbmi": {$sum: "$bmi"},
        "minbmi": {$min: "$bmi"},
        "maxbmi": {$max: "$bmi"}
    }
}, {
    $sort: {_id: 1}
}])

结果是:

{
    "_id" : "Afghanistan",
    "weight" : 2729.14,
    "height" : 6587.53,
    "avgbmi" : 24.8445707030224,
    "sumbmi" : 968.938257417875,
    "minbmi" : 17.0990239681871,
    "maxbmi" : 31.6807242778146
}
...

目前我正在尝试将其重写为 map-reduce。但是在这里我遇到了找到最小值和最大值的问题。到目前为止,我有:

var mapFunction2 = function() {
                           var key = this.nationality
                           var value = {
                                         count: 1,
                                         weight: this.weight,
                                         height: this.height,
                                         sumbmi: parseFloat(this.weight)/(parseFloat(this.height)/100 * parseFloat(this.height)/100)
                                       };
                           emit(key, value);
                    };

var reduceFunction2 = function(key, values) {
    reducedVal = { count: 0, weight: 0 , height: 0, sumbmi: 0, minbmi: 0, maxbmi: 0};
    for (var idx = 0; idx < values.length; idx++) {
            reducedVal.count += values[idx].count;
            var weight = parseFloat(values[idx].weight);
            var height = parseFloat(values[idx].height);
            reducedVal.weight += weight;
            reducedVal.height += height;
            reducedVal.sumbmi += values[idx].sumbmi;
    }
    return reducedVal;
};

var finalizeFunction2 = function (key, reducedVal) {
    reducedVal.avgbmi = parseFloat(reducedVal.sumbmi)/reducedVal.count;
    return reducedVal;
};

db.getCollection('people').mapReduce( mapFunction2, reduceFunction2,  {finalize:finalizeFunction2, out:{inline:1}}).results

我这里有问题,因为我的最小值和最大值很奇怪......?(最小值约为 20,但最大值为 940,reduce 中的数组长度 == 3)

你能帮助我吗?先感谢您。

标签: mongodbmapreduceaggregation-framework

解决方案


推荐阅读