MongoDB的reduce功能未运行



我已经将下面的sql语句翻译为map reduce:

select
    p_brand,    p_type,     p_size, 
    count(ps_suppkey) as supplier_cnt
from 
    partsupp, part
where 
    p_partkey = ps_partkey
    and p_brand <> 'Brand#45'
    and p_type not like 'MEDIUM POLISHED %'
    and p_size in (49, 14, 23, 45, 19, 3, 36, 9)
    and ps_suppkey not in (
            select 
            s_suppkey
            from 
            supplier
            where 
            s_comment like '%Customer%Complaints%'
        )
group by 
    p_brand, p_type, p_size
order by 
    supplier_cnt desc, p_brand, p_type, p_size;

Map reduce函数:

db.runCommand({
    mapreduce: "partsupp",
    query: {
        "ps_partkey.p_size": { $in: [49, 14, 23, 45, 19, 3, 36, 9] },
        "ps_partkey.p_brand": { $ne: "Brand#45" }
    },
    map: function() {
        var pattern1 = /^MEDIUM POLISHED .*/;
        var pattern2 = /.*Customer.*Complaints.*/;
        var suppkey = this.ps_suppkey.s_suppkey;
        if( this.ps_suppkey.s_comment.match(pattern1) == null ){
            if(this.ps_suppkey.s_comment.match(pattern2) != null){
                emit({p_brand: this.ps_partkey.p_brand, p_type: this.ps_partkey.p_type, p_size: this.ps_partkey.p_size}, suppkey);
            }
        }
    },
    reduce: function(key, values) {
        return values.length;
    },
    out: 'query016'
});

输出结果(在我看来)没有一个减少:

{
        "result" : "query016",
        "timeMillis" : 46862,
        "counts" : {
                "input" : 122272,
                "emit" : 54,
                "reduce" : 0,
                "output" : 54
        },
        "ok" : 1
}

什么错了吗?

map函数输出键和值对。

reduce函数的目的是为同一个键组合多个值。这意味着如果某个键值只发出一次,那么它只有一个值,并且没有什么可减少的。

这就是为什么在emit语句中输出的值必须与reduce函数返回的格式完全相同的原因之一。

地图输出:

emit(key1, valueX);
emit(key1, valueY);
emit(key2, valueZ);

Reduce将valueX和valueY组合起来返回key1的新valueXY,最终结果将是:

key1, valueXY
key, valueZ

注意,在key2上从来没有调用过reduce。对于每个键值,Reduce函数可能被调用零,一次或多次,因此您必须小心构造map和Reduce函数以允许这种可能性。

你的map函数没有发出一个正确的值——你想计数,所以你必须输出一个计数。您的reduce函数必须循环遍历已经累积的计数,并将它们相加并返回组合计数。您可能想看看MongoDB文档中提供的一些示例。

你可以使用聚合框架来做这个更简单的事情——我不认为这里需要MapReduce,除非你期望输出大量的结果。

我怀疑你叫emit(value,key)而不是emit(key,value)

如前所述,映射值和简化后的值必须具有相同的结构。如果你只是想做一个计数,映射一个值=1,在减少函数只是返回Array.sum(values)

最新更新