You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@couchdb.apache.org by ii...@apache.org on 2025/06/27 17:15:49 UTC
(couchdb) 04/05: Split query function into query_{group_by|sort_by|count_by}
This is an automated email from the ASF dual-hosted git repository.
iilyak pushed a commit to branch couch-stats-resource-tracker-v3-rebase-http-2
in repository https://gitbox.apache.org/repos/asf/couchdb.git
commit 3c27b489e8515bb3d6a2bd89dab262c0d916498b
Author: ILYA Khlopotov <ii...@apache.org>
AuthorDate: Fri Jun 27 09:42:12 2025 -0700
Split query function into query_{group_by|sort_by|count_by}
---
.../src/couch_stats_resource_tracker.hrl | 2 +-
src/couch_stats/src/csrt.erl | 64 ++++++++++++++++---
src/couch_stats/src/csrt_httpd.erl | 6 +-
src/couch_stats/src/csrt_query.erl | 73 ++++++++++++----------
4 files changed, 99 insertions(+), 46 deletions(-)
diff --git a/src/couch_stats/src/couch_stats_resource_tracker.hrl b/src/couch_stats/src/couch_stats_resource_tracker.hrl
index bf03a88b4..aba38c16e 100644
--- a/src/couch_stats/src/couch_stats_resource_tracker.hrl
+++ b/src/couch_stats/src/couch_stats_resource_tracker.hrl
@@ -191,7 +191,7 @@
-type tuple_of_field_values() :: tuple().
-type tuple_of_field_names() :: tuple().
--type query_options() :: #{aggregation => group_by | sort_by | count_by, limit => pos_integer()}.
+-type query_options() :: #{limit => pos_integer()}.
-type aggregation_key() :: tuple_of_field_names().
-type aggregation_values() :: tuple_of_field_values().
-type query_result() :: #{aggregation_key() => non_neg_integer()}.
diff --git a/src/couch_stats/src/csrt.erl b/src/couch_stats/src/csrt.erl
index 1864f9f44..1efdf5ec3 100644
--- a/src/couch_stats/src/csrt.erl
+++ b/src/couch_stats/src/csrt.erl
@@ -92,8 +92,12 @@
find_workers_by_pidref/1,
group_by/2,
group_by/3,
- query/2,
- query/4,
+ query_group_by/3,
+ query_group_by/4,
+ query_sort_by/3,
+ query_sort_by/4,
+ query_count_by/2,
+ query_count_by/3,
query_matcher/1,
query_matcher/2,
sorted/1,
@@ -495,21 +499,63 @@ query_matcher(MatcherName) ->
query_matcher(MatcherName, Limit) ->
csrt_query:query_matcher(MatcherName, Limit).
--spec query(MatcherName :: string(), Keys :: binary() | rctx_field() | [binary()] | [rctx_field()]) ->
+-spec query_group_by(MatcherName, AggregationKeys, ValueKey) ->
{ok, query_result()}
- | {error, any()}.
-query(MatcherName, AggregationKeys) ->
- csrt_query:query(MatcherName, AggregationKeys).
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()],
+ ValueKey :: binary() | rctx_field().
+query_group_by(MatcherName, AggregationKeys, ValueKey) ->
+ csrt_query:query_group_by(MatcherName, AggregationKeys, ValueKey, #{}).
+
+-spec query_group_by(MatcherName, AggregationKeys, ValueKey, Options :: query_options()) ->
+ {ok, query_result()}
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()],
+ ValueKey :: binary() | rctx_field().
+query_group_by(MatcherName, AggregationKeys, ValueKey, Options) ->
+ csrt_query:query_group_by(MatcherName, AggregationKeys, ValueKey, Options).
+
+-spec query_sort_by(MatcherName, AggregationKeys, ValueKey) ->
+ {ok, query_result()}
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()],
+ ValueKey :: binary() | rctx_field().
+query_sort_by(MatcherName, AggregationKeys, ValueKey) ->
+ csrt_query:query_sort_by(MatcherName, AggregationKeys, ValueKey, #{}).
--spec query(MatcherName, AggregationKeys, ValueKey, Options :: query_options()) ->
+-spec query_sort_by(MatcherName, AggregationKeys, ValueKey, Options :: query_options()) ->
{ok, query_result()}
| {error, any()}
when
MatcherName :: string(),
AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()],
ValueKey :: binary() | rctx_field().
-query(MatcherName, AggregationKeys, ValueKey, Options) ->
- csrt_query:query(MatcherName, AggregationKeys, ValueKey, Options).
+query_sort_by(MatcherName, AggregationKeys, ValueKey, Options) ->
+ csrt_query:query_sort_by(MatcherName, AggregationKeys, ValueKey, Options).
+
+-spec query_count_by(MatcherName, AggregationKeys) ->
+ {ok, query_result()}
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()].
+query_count_by(MatcherName, AggregationKeys) ->
+ csrt_query:query_count_by(MatcherName, AggregationKeys, #{}).
+
+-spec query_count_by(MatcherName, AggregationKeys, Options :: query_options()) ->
+ {ok, query_result()}
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()].
+query_count_by(MatcherName, AggregationKeys, Options) ->
+ csrt_query:query_count_by(MatcherName, AggregationKeys, Options).
sorted(Map) ->
csrt_query:sorted(Map).
diff --git a/src/couch_stats/src/csrt_httpd.erl b/src/couch_stats/src/csrt_httpd.erl
index 577651205..3fb4f0212 100644
--- a/src/couch_stats/src/csrt_httpd.erl
+++ b/src/couch_stats/src/csrt_httpd.erl
@@ -64,7 +64,7 @@ handle_resource_status_req(Req) ->
handle_count_by(Req, MatcherName, CountBy) ->
AggregationKeys = couch_util:get_value(<<"aggregate_keys">>, CountBy),
- case csrt:query(MatcherName, AggregationKeys, undefined, #{aggregation => count_by}) of
+ case csrt:query_count_by(MatcherName, AggregationKeys) of
{ok, Map} ->
send_json(Req, {aggregation_result_to_json(Map)});
Else ->
@@ -75,7 +75,7 @@ handle_count_by(Req, MatcherName, CountBy) ->
handle_sort_by(Req, MatcherName, SortBy) ->
AggregationKeys = couch_util:get_value(<<"aggregate_keys">>, SortBy),
CounterKey = couch_util:get_value(<<"counter_key">>, SortBy),
- case csrt:query(MatcherName, AggregationKeys, CounterKey, #{aggregation => sort_by}) of
+ case csrt:query_sort_by(MatcherName, AggregationKeys, CounterKey) of
{ok, Map} ->
send_json(Req, {aggregation_result_to_json(Map)});
Else ->
@@ -86,7 +86,7 @@ handle_sort_by(Req, MatcherName, SortBy) ->
handle_group_by(Req, MatcherName, GroupBy) ->
AggregationKeys = couch_util:get_value(<<"aggregate_keys">>, GroupBy),
CounterKey = couch_util:get_value(<<"counter_key">>, GroupBy),
- case csrt:query(MatcherName, AggregationKeys, CounterKey, #{aggregation => group_by}) of
+ case csrt:query_group_by(MatcherName, AggregationKeys, CounterKey) of
{ok, Map} ->
send_json(Req, {aggregation_result_to_json(Map)});
Else ->
diff --git a/src/couch_stats/src/csrt_query.erl b/src/couch_stats/src/csrt_query.erl
index f96e3fc65..bacc44db3 100644
--- a/src/couch_stats/src/csrt_query.erl
+++ b/src/couch_stats/src/csrt_query.erl
@@ -34,8 +34,9 @@
find_workers_by_pidref/1,
group_by/3,
group_by/4,
- query/2,
- query/4,
+ query_group_by/4,
+ query_sort_by/4,
+ query_count_by/3,
query_matcher/1,
query_matcher/2,
query_matcher_rows/1,
@@ -322,14 +323,27 @@ get_matcher(MatcherName) ->
{ok, Matcher}
end.
--spec query(MatcherName :: string(), Keys :: binary() | rctx_field() | [binary()] | [rctx_field()]) ->
+-spec query_group_by(MatcherName, AggregationKeys, ValueKey, Options :: query_options()) ->
{ok, query_result()}
- | {error, any()}.
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()],
+ ValueKey :: binary() | rctx_field().
%% {ok, #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2}}
-query(MatcherName, AggregationKeys) ->
- query(MatcherName, AggregationKeys, undefined, #{}).
+query_group_by(MatcherName, AggregationKeys, ValueKey, Options) ->
+ AggregationKey = parse_key(AggregationKeys),
+ VKey = parse_key(ValueKey),
+ Limit = maps:get(limit, Options, query_limit()),
+ maybe
+ ok ?= validate_not_error(AggregationKey),
+ ok ?= validate_not_error(VKey),
+ ok ?= validate_limit(Limit),
+ {ok, Matcher} ?= get_matcher(MatcherName),
+ group_by(Matcher, AggregationKey, VKey)
+ end.
--spec query(MatcherName, AggregationKeys, ValueKey, Options :: query_options()) ->
+-spec query_sort_by(MatcherName, AggregationKeys, ValueKey, Options :: query_options()) ->
{ok, query_result()}
| {error, any()}
when
@@ -337,29 +351,33 @@ when
AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()],
ValueKey :: binary() | rctx_field().
%% {ok, #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2}}
-query(MatcherName, AggregationKeys, ValueKey, Options) ->
+query_sort_by(MatcherName, AggregationKeys, ValueKey, Options) ->
AggregationKey = parse_key(AggregationKeys),
VKey = parse_key(ValueKey),
Limit = maps:get(limit, Options, query_limit()),
- Aggregation = maps:get(aggregation, Options, none),
maybe
ok ?= validate_not_error(AggregationKey),
ok ?= validate_not_error(VKey),
ok ?= validate_limit(Limit),
- ok ?= validate_aggregation(Aggregation),
{ok, Matcher} ?= get_matcher(MatcherName),
- case Aggregation of
- group_by ->
- group_by(Matcher, AggregationKey, VKey);
- sort_by ->
- sort_by(Matcher, AggregationKey, VKey);
- count_by when VKey == undefined ->
- count_by(Matcher, AggregationKey);
- count_by ->
- {error, {extra_argument, value_key}};
- none ->
- query_matcher_rows(Matcher, Limit)
- end
+ sort_by(Matcher, AggregationKey, VKey)
+ end.
+
+-spec query_count_by(MatcherName, AggregationKeys, Options :: query_options()) ->
+ {ok, query_result()}
+ | {error, any()}
+when
+ MatcherName :: string(),
+ AggregationKeys :: binary() | rctx_field() | [binary()] | [rctx_field()].
+%% {ok, #{{<<"adm">>,<<"bench-yktbb3as46rzffea">>} => 2}}
+query_count_by(MatcherName, AggregationKeys, Options) ->
+ AggregationKey = parse_key(AggregationKeys),
+ Limit = maps:get(limit, Options, query_limit()),
+ maybe
+ ok ?= validate_not_error(AggregationKey),
+ ok ?= validate_limit(Limit),
+ {ok, Matcher} ?= get_matcher(MatcherName),
+ count_by(Matcher, AggregationKey)
end.
validate_not_error({error, _} = Error) ->
@@ -380,17 +398,6 @@ validate_limit(Limit) when is_integer(Limit) ->
validate_limit(Limit) ->
{error, {invalid_limit, Limit}}.
-validate_aggregation(none) ->
- ok;
-validate_aggregation(group_by) ->
- ok;
-validate_aggregation(sort_by) ->
- ok;
-validate_aggregation(count_by) ->
- ok;
-validate_aggregation(Other) ->
- {error, {invalid_aggregation, Other}}.
-
-spec parse_key(Keys :: binary() | atom() | [binary()] | [atom()]) ->
[rctx_field()]
| throw({bad_request, Reason :: binary()}).