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

How to get sum, averages etc. from a nested array of numbers in documents in 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[] 和 adding/removing if 语句,但没有成功。

如果可能的话,我也希望能对数组的这种变体提供帮助。

由于某些原因,在 map/reduce 中设置 javascript 并不容易。 我已经参加了很多免费的在线 javascript 学习课程来尝试提高我使用 CouchDB 的能力,但没有取得太大的成功。 有没有更好的方法来学习为 map reduce 编写正确 javascript 的黑暗艺术?

非常感谢您的帮助。

由于您想要 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);
        }
    }
}