You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by va...@apache.org on 2025/03/26 17:08:14 UTC
(couchdb) branch topn created (now 239bd83a2)
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a change to branch topn
in repository https://gitbox.apache.org/repos/asf/couchdb.git
at 239bd83a2 Implement topN/bottomN built-in reducers
This branch includes the following new commits:
new 239bd83a2 Implement topN/bottomN built-in reducers
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
(couchdb) 01/01: Implement topN/bottomN built-in reducers
Posted by va...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
vatamane pushed a commit to branch topn
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 239bd83a2a9f7af5f151eab93b0145368bf9ba29
Author: Nick Vatamaniuc <va...@gmail.com>
AuthorDate: Wed Mar 26 13:03:37 2025 -0400
Implement topN/bottomN built-in reducers
These should help use the already existing grouping and key sorting
functionality to kepe track of last update time, or top sales numbers or
anything of that sort.
It's a bit tricky to have options for built-in reducers, so start with a few
powers of ten: 1, 10, 100.
---
src/couch/src/couch_query_servers.erl | 35 ++++++++++++++++++++++++++++++++++-
src/couch_mrview/src/couch_mrview.erl | 12 ++++++++++++
2 files changed, 46 insertions(+), 1 deletion(-)
diff --git a/src/couch/src/couch_query_servers.erl b/src/couch/src/couch_query_servers.erl
index 6789bfaef..10e55b26a 100644
--- a/src/couch/src/couch_query_servers.erl
+++ b/src/couch/src/couch_query_servers.erl
@@ -196,7 +196,25 @@ builtin_reduce(Re, [<<"_stats", _/binary>> | BuiltinReds], KVs, Acc) ->
builtin_reduce(Re, BuiltinReds, KVs, [Stats | Acc]);
builtin_reduce(Re, [<<"_approx_count_distinct", _/binary>> | BuiltinReds], KVs, Acc) ->
Distinct = approx_count_distinct(Re, KVs),
- builtin_reduce(Re, BuiltinReds, KVs, [Distinct | Acc]).
+ builtin_reduce(Re, BuiltinReds, KVs, [Distinct | Acc]);
+builtin_reduce(Re, [<<"_top100", _/binary>> | BuiltinReds], KVs, Acc) ->
+ Top = builtin_rank_n(Re, fun rank_fun_top/2, 100, KVs),
+ builtin_reduce(Re, BuiltinReds, KVs, [Top | Acc]);
+builtin_reduce(Re, [<<"_top10", _/binary>> | BuiltinReds], KVs, Acc) ->
+ Top = builtin_rank_n(Re, fun rank_fun_top/2, 10, KVs),
+ builtin_reduce(Re, BuiltinReds, KVs, [Top | Acc]);
+builtin_reduce(Re, [<<"_top1", _/binary>> | BuiltinReds], KVs, Acc) ->
+ Top = builtin_rank_n(Re, fun rank_fun_top/2, 1, KVs),
+ builtin_reduce(Re, BuiltinReds, KVs, [Top | Acc]);
+builtin_reduce(Re, [<<"_bottom100", _/binary>> | BuiltinReds], KVs, Acc) ->
+ Bottom = builtin_rank_n(Re, fun rank_fun_bottom/2, 100, KVs),
+ builtin_reduce(Re, BuiltinReds, KVs, [Bottom | Acc]);
+builtin_reduce(Re, [<<"_bottom10", _/binary>> | BuiltinReds], KVs, Acc) ->
+ Bottom = builtin_rank_n(Re, fun rank_fun_bottom/2, 10, KVs),
+ builtin_reduce(Re, BuiltinReds, KVs, [Bottom | Acc]);
+builtin_reduce(Re, [<<"_bottom1", _/binary>> | BuiltinReds], KVs, Acc) ->
+ Bottom = builtin_rank_n(Re, fun rank_fun_bottom/2, 1, KVs),
+ builtin_reduce(Re, BuiltinReds, KVs, [Bottom | Acc]).
builtin_sum_rows([], Acc) ->
Acc;
@@ -385,6 +403,21 @@ approx_count_distinct(reduce, KVs) ->
approx_count_distinct(rereduce, Reds) ->
couch_hyper:union([Filter || [_, Filter] <- Reds]).
+builtin_rank_n(reduce, RankFun, N, KVs) when is_integer(N), N > 0 ->
+ Fun = fun([[_Key, _Id], Value], Acc) -> lists:umerge(RankFun, Acc, [Value]) end,
+ lists:sublist(lists:foldl(Fun, [], KVs), N);
+builtin_rank_n(rereduce, _Rank, N, []) when is_integer(N), N > 0 ->
+ [];
+builtin_rank_n(rereduce, RankFun, N, [[_, KVs0] | Rest]) when is_integer(N), N > 0 ->
+ Fun = fun([_, KVs], Acc) -> lists:umerge(RankFun, Acc, KVs) end,
+ lists:sublist(lists:foldl(Fun, KVs0, Rest), N).
+
+rank_fun_top(A, B) ->
+ couch_ejson_compare:less(A, B) > 0.
+
+rank_fun_bottom(A, B) ->
+ couch_ejson_compare:less(A, B) < 0.
+
% use the function stored in ddoc.validate_doc_update to test an update.
-spec validate_doc_update(Db, DDoc, EditDoc, DiskDoc, Ctx, SecObj) -> ok when
Db :: term(),
diff --git a/src/couch_mrview/src/couch_mrview.erl b/src/couch_mrview/src/couch_mrview.erl
index d126e30cc..182c6d3cf 100644
--- a/src/couch_mrview/src/couch_mrview.erl
+++ b/src/couch_mrview/src/couch_mrview.erl
@@ -211,6 +211,18 @@ validate(Db, DDoc) ->
ok;
({_RedName, <<"_approx_count_distinct", _/binary>>}) ->
ok;
+ ({_RedName, <<"_top1", _/binary>>}) ->
+ ok;
+ ({_RedName, <<"_top10", _/binary>>}) ->
+ ok;
+ ({_RedName, <<"_top100", _/binary>>}) ->
+ ok;
+ ({_RedName, <<"_bottom1", _/binary>>}) ->
+ ok;
+ ({_RedName, <<"_bottom10", _/binary>>}) ->
+ ok;
+ ({_RedName, <<"_bottom100", _/binary>>}) ->
+ ok;
({_RedName, <<"_", _/binary>> = Bad}) ->
Msg = ["`", Bad, "` is not a supported reduce function."],
throw({invalid_design_doc, Msg});