如何从Couchdb中的文档中的嵌套数字数组中获得总和,平均值等

时间:2016-09-27 11:03:28

标签: arrays mapreduce nested couchdb

我有一个CouchDB数据库,其中的文档包含如下数据:

"field1": "text",
"field2": "text",
"field3":[14 54 23 24,25,26,23,19,17 etc.]
etc.

我正在尝试使用map reduce来获取数据库中所有field3值的平均值。

我做了如下地图:

function(doc) {
if(doc.field3){
emit(null,doc.field3);
}
}

和减少:

function (keys, values, rereduce) {
if (rereduce){
return sum(values);
} else {
return values.length;
}
}

或简单地说:

_sum

后者给出了一系列数字,这些数字似乎是数组中相同数字的总和。

Cloudant网站上有一个例子涉及访问一组数字,但不是完整的答案,我现在找不到它。

我还调查了CouchDB 2.0.0上的新'mango'查询系统,它更容易设置,但我没有在文档中看到任何使用它进行计算的方法。

修改

允许我自由地加上这个问题,或许是一个很好的例子。

我正在使用Mockaroo生成数据并找到了另一种生成此数据的方法,这种方法更加真实,因为我可以改变数据的更多方面。

然而,这导致我的数组发生以下更改:

"field3":[{"item": 44}, {"item":23}, {"item": 36}, etc.]

使用@Alexis提供的成功地图,我试图让它读取这些数据。例如:

function(doc) {
if(doc.field3[0].item >0){
if (doc.field3) {
    if (Array.isArray(doc.field3))
        for (var n in doc.field3)
            emit(null, doc.field3[n].item);
}
}
}

我尝试了上述代码的多种变体,添加了.item[]以及添加/删除if语句,但没有成功。

如果可能的话,我也非常感谢数组变体的帮助。

由于某种原因,在map / reduce中设置javascript并不容易。 我已经通过相当多的免费在线JavaScript学习课程来尝试使用CouchDB提高我的能力,但没有取得多大成功。 是否有更好的方法来学习为地图缩小编写正确的javascript的黑暗艺术?

非常感谢你的帮助。

1 个答案:

答案 0 :(得分:1)

由于你希望field3上的全局平均值是一个数组,我首先会映射所有字段3的值并将它们全部减少。

地图功能:

function(doc) {
    if (doc.field3) {
        if (Array.isArray(doc.field3))
            for (var n in doc.field3)
                emit(null, doc.field3[n]);
    }
}

减少功能:

function(keys, values, rereduce) {
    return sum(values)/values.length;
}

新修改意味着新答案!

//Your function

function(doc) {
    if (doc.field3[0].item > 0) {
        if (doc.field3) {
            if (Array.isArray(doc.field3))
                for (var n in doc.field3)
                    emit(null, doc.field3[n].item);
        }
    }
}

//Fixed one

function(doc){
    //We check if the field3 is an array and we check if its length is 
    //true. In javascript 0==false, any number ==true  and the length can't 
    // be negative so we are in business.
    if(Array.isArray(doc.field3) && doc.field3.length){ 
        //Your array contains many object. So we can simply iterate through them
        for(var i=0;i<doc.field3.length;i++){
            //at this point, doc.field3[i] is one of the object. Eg: {"item":44}
            emit(null,doc.field3[i].item);
        }
    }
}