diff options
author | Adam Kocoloski <kocolosk@apache.org> | 2010-03-10 22:12:13 +0000 |
---|---|---|
committer | Adam Kocoloski <kocolosk@apache.org> | 2010-03-10 22:12:13 +0000 |
commit | 68ac2db910581555b9f3063bba2421c8fc2b391b (patch) | |
tree | 1c8681b1642a6a214023249698e6884ab6817809 | |
parent | b9f749b5529af985abcb53681244416fe8e2b4cc (diff) |
_stats builtin reduction for min/max/mean/variance
git-svn-id: https://svn.apache.org/repos/asf/couchdb/trunk@921592 13f79535-47bb-0310-9956-ffa450edef68
-rw-r--r-- | share/www/script/test/reduce_builtin.js | 14 | ||||
-rw-r--r-- | src/couchdb/couch_query_servers.erl | 23 |
2 files changed, 36 insertions, 1 deletions
diff --git a/share/www/script/test/reduce_builtin.js b/share/www/script/test/reduce_builtin.js index 7938a0cf..0db6bc09 100644 --- a/share/www/script/test/reduce_builtin.js +++ b/share/www/script/test/reduce_builtin.js @@ -22,6 +22,14 @@ couchTests.reduce_builtin = function(debug) { var summate = function(N) {return (N+1)*N/2;}; + var sumsqr = function(N) { + var acc = 0; + for (var i=1; i<=N; ++i) { + acc += i*i; + } + return acc; + } + // this is the same test as the reduce.js test // only we'll let CouchDB run reduce in Erlang var map = function (doc) { @@ -32,6 +40,12 @@ couchTests.reduce_builtin = function(debug) { T(result.rows[0].value == 2*summate(numDocs)); result = db.query(map, "_count"); T(result.rows[0].value == 1000); + result = db.query(map, "_stats"); + T(result.rows[0].value.sum == 2*summate(numDocs)); + T(result.rows[0].value.count == 1000); + T(result.rows[0].value.min == 1); + T(result.rows[0].value.max == 500); + T(result.rows[0].value.sumsqr == 2*sumsqr(numDocs)); result = db.query(map, "_sum", {startkey: 4, endkey: 4}); T(result.rows[0].value == 8); diff --git a/src/couchdb/couch_query_servers.erl b/src/couchdb/couch_query_servers.erl index 3095b199..ff89a67a 100644 --- a/src/couchdb/couch_query_servers.erl +++ b/src/couchdb/couch_query_servers.erl @@ -154,7 +154,10 @@ builtin_reduce(reduce, [<<"_count">>|BuiltinReds], KVs, Acc) -> builtin_reduce(reduce, BuiltinReds, KVs, [Count|Acc]); builtin_reduce(rereduce, [<<"_count">>|BuiltinReds], KVs, Acc) -> Count = builtin_sum_rows(KVs), - builtin_reduce(rereduce, BuiltinReds, KVs, [Count|Acc]). + builtin_reduce(rereduce, BuiltinReds, KVs, [Count|Acc]); +builtin_reduce(Re, [<<"_stats">>|BuiltinReds], KVs, Acc) -> + Stats = builtin_stats(Re, KVs), + builtin_reduce(Re, BuiltinReds, KVs, [Stats|Acc]). builtin_sum_rows(KVs) -> lists:foldl(fun @@ -164,6 +167,24 @@ builtin_sum_rows(KVs) -> throw({invalid_value, <<"builtin _sum function requires map values to be numbers">>}) end, 0, KVs). +builtin_stats(reduce, [[_,First]|Rest]) when is_number(First) -> + Stats = lists:foldl(fun([_K,V], {S,C,Mi,Ma,Sq}) when is_number(V) -> + {S+V, C+1, erlang:min(Mi,V), erlang:max(Ma,V), Sq+(V*V)}; + (_, _) -> + throw({invalid_value, + <<"builtin _stats function requires map values to be numbers">>}) + end, {First,1,First,First,First*First}, Rest), + {Sum, Cnt, Min, Max, Sqr} = Stats, + {[{sum,Sum}, {count,Cnt}, {min,Min}, {max,Max}, {sumsqr,Sqr}]}; + +builtin_stats(rereduce, [[_,First]|Rest]) -> + {[{sum,Sum0}, {count,Cnt0}, {min,Min0}, {max,Max0}, {sumsqr,Sqr0}]} = First, + Stats = lists:foldl(fun([_K,Red], {S,C,Mi,Ma,Sq}) -> + {[{sum,Sum}, {count,Cnt}, {min,Min}, {max,Max}, {sumsqr,Sqr}]} = Red, + {Sum+S, Cnt+C, erlang:min(Min,Mi), erlang:max(Max,Ma), Sqr+Sq} + end, {Sum0,Cnt0,Min0,Max0,Sqr0}, Rest), + {Sum, Cnt, Min, Max, Sqr} = Stats, + {[{sum,Sum}, {count,Cnt}, {min,Min}, {max,Max}, {sumsqr,Sqr}]}. % use the function stored in ddoc.validate_doc_update to test an update. validate_doc_update(DDoc, EditDoc, DiskDoc, Ctx, SecObj) -> |