summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRobert Newson <rnewson@apache.org>2023-05-10 10:21:35 +0100
committerRobert Newson <rnewson@apache.org>2023-05-10 14:42:24 +0100
commit51267a5fd170c865cba795b5af3f7d3f348caed5 (patch)
treefba244a7a73f6e16796e01e408b2616c7b13a6c8
parent9851bb396a8511c0317365dab2d7585cf86a0e3f (diff)
downloadcouchdb-51267a5fd170c865cba795b5af3f7d3f348caed5.tar.gz
Improve nouveau mango integration
1) Fix sorting on strings and numbers 2) use 'string' type for string fields 3) use 'text' type for the default field
-rw-r--r--src/mango/src/mango_cursor_nouveau.erl10
-rw-r--r--src/mango/src/mango_error.erl11
-rw-r--r--src/mango/src/mango_idx_nouveau.erl2
-rw-r--r--src/mango/src/mango_native_proc.erl15
-rw-r--r--test/elixir/test/config/nouveau.elixir3
-rw-r--r--test/elixir/test/nouveau_test.exs51
6 files changed, 85 insertions, 7 deletions
diff --git a/src/mango/src/mango_cursor_nouveau.erl b/src/mango/src/mango_cursor_nouveau.erl
index 7cdad20cd..1758e5dcc 100644
--- a/src/mango/src/mango_cursor_nouveau.erl
+++ b/src/mango/src/mango_cursor_nouveau.erl
@@ -222,7 +222,15 @@ sort_query(Opts, Selector) ->
{Field, <<"desc">>} -> {desc, Field};
Field when is_binary(Field) -> {asc, Field}
end,
- SField = mango_selector_text:append_sort_type(RawSortField, Selector),
+ SField0 = mango_selector_text:append_sort_type(RawSortField, Selector),
+ %% ugly fixup below
+ SField =
+ case SField0 of
+ <<Prefix:(size(SField0) - 8)/binary, "<number>">> ->
+ <<Prefix/binary, "<double>">>;
+ Else ->
+ Else
+ end,
case Dir of
asc ->
SField;
diff --git a/src/mango/src/mango_error.erl b/src/mango/src/mango_error.erl
index 22cb37106..a8b5bfa4b 100644
--- a/src/mango/src/mango_error.erl
+++ b/src/mango/src/mango_error.erl
@@ -94,6 +94,17 @@ info(mango_cursor_nouveau, {nouveau_search_error, {error, Error}}) ->
<<"nouveau_search_error">>,
fmt("~p", [Error])
};
+info(mango_idx_nouveau, {invalid_index_fields_definition, Def}) ->
+ {
+ 400,
+ <<"invalid_index_fields_definition">>,
+ fmt(
+ "Text Index field definitions must be of the form\n"
+ " {\"name\": \"non-empty fieldname\", \"type\":\n"
+ " \"boolean,number,string or text\"}. Def: ~p",
+ [Def]
+ )
+ };
info(mango_fields, {invalid_fields_json, BadFields}) ->
{
400,
diff --git a/src/mango/src/mango_idx_nouveau.erl b/src/mango/src/mango_idx_nouveau.erl
index 074a755ee..0816898a1 100644
--- a/src/mango/src/mango_idx_nouveau.erl
+++ b/src/mango/src/mango_idx_nouveau.erl
@@ -181,6 +181,8 @@ validate_field_name(Else) when is_binary(Else) ->
validate_field_name(_) ->
throw(invalid_field_name).
+validate_field_type(<<"text">>) ->
+ <<"text">>;
validate_field_type(<<"string">>) ->
<<"string">>;
validate_field_type(<<"number">>) ->
diff --git a/src/mango/src/mango_native_proc.erl b/src/mango/src/mango_native_proc.erl
index 8e04ab4b8..7982fc787 100644
--- a/src/mango/src/mango_native_proc.erl
+++ b/src/mango/src/mango_native_proc.erl
@@ -254,7 +254,10 @@ add_default_text_field(Fields) ->
add_default_text_field([], Acc) ->
Acc;
add_default_text_field([{_Name, <<"string">>, Value} | Rest], Acc) ->
- NewAcc = [{<<"$default">>, <<"string">>, Value} | Acc],
+ NewAcc = [{<<"$default">>, <<"text">>, Value} | Acc],
+ add_default_text_field(Rest, NewAcc);
+add_default_text_field([{_Name, <<"text">>, Value} | Rest], Acc) ->
+ NewAcc = [{<<"$default">>, <<"text">>, Value} | Acc],
add_default_text_field(Rest, NewAcc);
add_default_text_field([_ | Rest], Acc) ->
add_default_text_field(Rest, Acc).
@@ -310,6 +313,8 @@ get_text_field_type(<<"number">>) ->
<<"number">>;
get_text_field_type(<<"boolean">>) ->
<<"boolean">>;
+get_text_field_type(<<"text">>) ->
+ <<"text">>;
get_text_field_type(_) ->
<<"string">>.
@@ -359,6 +364,14 @@ convert_nouveau_fields([]) ->
convert_nouveau_fields([{Name, <<"string">>, Value} | Rest]) ->
Field =
{[
+ {<<"@type">>, <<"string">>},
+ {<<"name">>, Name},
+ {<<"value">>, Value}
+ ]},
+ [Field | convert_nouveau_fields(Rest)];
+convert_nouveau_fields([{Name, <<"text">>, Value} | Rest]) ->
+ Field =
+ {[
{<<"@type">>, <<"text">>},
{<<"name">>, Name},
{<<"value">>, Value}
diff --git a/test/elixir/test/config/nouveau.elixir b/test/elixir/test/config/nouveau.elixir
index 5c13aac2b..a580581e6 100644
--- a/test/elixir/test/config/nouveau.elixir
+++ b/test/elixir/test/config/nouveau.elixir
@@ -15,6 +15,9 @@
"ranges (open)",
"mango search by number",
"mango search by string",
+ "mango search by text",
+ "mango sort by number",
+ "mango sort by string",
"search GET (partitioned)",
"search POST (partitioned)",
"mango (partitioned)"
diff --git a/test/elixir/test/nouveau_test.exs b/test/elixir/test/nouveau_test.exs
index 3bea874d9..ad48e58ea 100644
--- a/test/elixir/test/nouveau_test.exs
+++ b/test/elixir/test/nouveau_test.exs
@@ -11,10 +11,10 @@ defmodule NouveauTest do
resp = Couch.post("/#{db_name}/_bulk_docs",
headers: ["Content-Type": "application/json"],
body: %{:docs => [
- %{"_id" => "doc4", "foo" => "foo", "bar" => 42},
- %{"_id" => "doc3", "foo" => "bar", "bar" => 12.0},
- %{"_id" => "doc1", "foo" => "baz", "bar" => 0},
- %{"_id" => "doc2", "foo" => "foobar", "bar" => 100},
+ %{"_id" => "doc4", "foo" => "foo", "bar" => 42, "baz" => "hello there"},
+ %{"_id" => "doc3", "foo" => "bar", "bar" => 12.0, "baz" => "hello"},
+ %{"_id" => "doc1", "foo" => "baz", "bar" => 0, "baz" => "there"},
+ %{"_id" => "doc2", "foo" => "foobar", "bar" => 100, "baz" => "hi"},
]}
)
assert resp.status_code in [201]
@@ -61,13 +61,15 @@ defmodule NouveauTest do
index: %{
fields: [
%{name: "foo", type: "string"},
- %{name: "bar", type: "number"}
+ %{name: "bar", type: "number"},
+ %{name: "baz", type: "string"},
]
}
}
resp = Couch.post("/#{db_name}/_index", body: body)
assert resp.status_code in [200]
+ resp.body
end
def get_ids(resp) do
@@ -303,6 +305,45 @@ defmodule NouveauTest do
assert ids == ["doc4"]
end
+ @tag :with_db
+ test "mango search by text", context do
+ db_name = context[:db_name]
+ create_search_docs(db_name)
+ create_mango_index(db_name)
+
+ url = "/#{db_name}/_find"
+ resp = Couch.post(url, body: %{selector: %{"$text": "hello"}})
+ assert_status_code(resp, 200)
+ ids = get_mango_ids(resp)
+ assert ids == ["doc4", "doc3"]
+ end
+
+ @tag :with_db
+ test "mango sort by number", context do
+ db_name = context[:db_name]
+ create_search_docs(db_name)
+ create_mango_index(db_name)
+
+ url = "/#{db_name}/_find"
+ resp = Couch.post(url, body: %{sort: [%{"bar:number": "asc"}], selector: %{bar: %{"$gt": 5}}})
+ assert_status_code(resp, 200)
+ ids = get_mango_ids(resp)
+ assert ids == ["doc3", "doc4", "doc2"]
+ end
+
+ @tag :with_db
+ test "mango sort by string", context do
+ db_name = context[:db_name]
+ create_search_docs(db_name)
+ create_mango_index(db_name)
+
+ url = "/#{db_name}/_find"
+ resp = Couch.post(url, body: %{sort: [%{"foo:string": "asc"}], selector: %{bar: %{"$gte": 0}}})
+ assert_status_code(resp, 200)
+ ids = get_mango_ids(resp)
+ assert ids == ["doc3", "doc1", "doc4", "doc2"]
+ end
+
@tag :with_partitioned_db
test "search GET (partitioned)", context do
db_name = context[:db_name]