walves
walves

Reputation: 2068

MongoDB map reduce function syntax

Well im trying translate this sql query to map reduce

select
    o_orderpriority, 
    count(*) as order_count
from 
    orders
where 
    o_orderdate >= date '1993-07-01'
    and o_orderdate < date '1993-07-01' + interval '3' month
    and exists (
        select 
        *
        from 
        lineitem
        where 
        l_orderkey = o_orderkey
        and l_commitdate < l_receiptdate
    )
group by 
    o_orderpriority
order by 
    o_orderpriority;

Ive tried the following map reduce function

    db.runCommand({
    mapreduce: "orders",
    query: {
        o_orderdate: {'$gte': new Date("July 01, 1993")},
        o_orderdate: {'$lt': new Date("Oct 01, 1993")}
    },
    map: function Map() {
            for(var i in this.o_lineitem) {
                if( this.o_lineitem[i].l_commitdate < this.o_lineitem[i].l_receiptdate) {
                    var o_orderpriority = this.o_lineitem[i].o_orderpriority;
                    emit( o_orderpriority, {count: 1} );
                }
            }
        },
    reduce: function(key, values) {
                var count= 0;
                for (var i = 0; i < values.length; i++) {
                    count+= values[i];
                }
                return count;
            },
    out: 'query004'
});

when a i run i get the follow alert

Sat Aug 11 20:44:32 SyntaxError: missing ) after condition (shell):9

For me there's no ) missing, is it there?

I did the corrections pointed by @Stenie, but now a i have the follow problem

{
        "assertion" : "value too large to reduce",
        "assertionCode" : 13070,
        "errmsg" : "db assertion failure",
        "ok" : 0
}

Upvotes: 2

Views: 1342

Answers (1)

Asya Kamsky
Asya Kamsky

Reputation: 42352

The problem is your emit and your reduce function do not return the same thing.

Your map function emits the value:

{count: 1}

That means your reduce must return the same format.

You are returning a simple value in your reduce:

return count;

You can change your emit to just emit 1 instead of JSON document and then you don't have to change your reduce, otherwise change your reduce to return a JSON document {count: X} where X is the computed count.

FYI, the reason this is causing the error "value too large to reduce" is that once you mix your types like this, the '+' operator starts concatenating your values rather than adding them and eventually it gets too large. To see how you could debug this I recommend the Troubleshooting MapReduce page

Upvotes: 3

Related Questions