From 6d17dc9de59d202a27be497e5da413a0080b91cb Mon Sep 17 00:00:00 2001 From: Alba Herrerias Date: Mon, 24 Nov 2025 15:02:31 +0000 Subject: [PATCH 1/2] Port choose correct index tests to Elixir --- test/elixir/test/config/suite.elixir | 14 +- .../test/mango/12_use_correct_index_test.exs | 139 ++++++++++++++++++ 2 files changed, 152 insertions(+), 1 deletion(-) create mode 100644 test/elixir/test/mango/12_use_correct_index_test.exs diff --git a/test/elixir/test/config/suite.elixir b/test/elixir/test/config/suite.elixir index b3fb950846..4236e0a545 100644 --- a/test/elixir/test/config/suite.elixir +++ b/test/elixir/test/config/suite.elixir @@ -735,5 +735,17 @@ ], "IgnoreDesignDocsForAllDocsIndexTests": [ "should not return design docs" - ] + ], + "ChooseCorrectIndexForDocs": [ + "choose index with one field in index", + "choose index with two", + "choose index alphabetically", + "choose index most accurate", + "choose index most accurate in memory selector", + "warn on full db scan", + "chooses idxA", + "can query with range on secondary column", + "choose index with id", + "choose index with rev" + ], } diff --git a/test/elixir/test/mango/12_use_correct_index_test.exs b/test/elixir/test/mango/12_use_correct_index_test.exs new file mode 100644 index 0000000000..627cc86cb7 --- /dev/null +++ b/test/elixir/test/mango/12_use_correct_index_test.exs @@ -0,0 +1,139 @@ +# Licensed under the Apache License, Version 2.0 (the "License"); you may not +# use this file except in compliance with the License. You may obtain a copy of +# the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT +# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the +# License for the specific language governing permissions and limitations under +# the License. + +defmodule ChooseCorrectIndexForDocs do + use CouchTestCase + + @db_name "choose-correct-index" + @docs [ + %{"_id" => "_design/my-design-doc"}, + %{ + "_id" => "54af50626de419f5109c962f", + "user_id" => 0, + "age" => 10, + "name" => "Jimi", + "location" => "UK", + "number" => 4, + }, + %{ + "_id" => "54af50622071121b25402dc3", + "user_id" => 1, + "age" => 12, + "name" => "Eddie", + "location" => "ZAR", + "number" => 2, + }, + %{ + "_id" => "54af50622071121b25402dc6", + "user_id" => 1, + "age" => 6, + "name" => "Harry", + "location" => "US", + "number" => 8, + }, + %{ + "_id" => "54af50622071121b25402dc9", + "name" => "Eddie", + "occupation" => "engineer", + "number" => 7, + }, + ] + @docs2 [%{"a" => 1, "b" => 1, "c" => 1}, %{"a" => 1000, "d" => 1000, "e" => 1000}] + + setup do + MangoDatabase.recreate(@db_name) + MangoDatabase.save_docs(@db_name, @docs) + :ok + end + + test "choose index with one field in index" do + MangoDatabase.create_index(@db_name, ["name", "age", "user_id"], ddoc: "aaa") + MangoDatabase.create_index(@db_name, ["name"], ddoc: "zzz") + {:ok, explain} = MangoDatabase.find(@db_name, %{"name" => "Eddie"}, explain: true) + assert explain["index"]["ddoc"] == "_design/zzz" + end + + test "choose index with two" do + MangoDatabase.create_index(@db_name, ["name", "age", "user_id"], ddoc: "aaa") + MangoDatabase.create_index(@db_name, ["name", "age"], ddoc: "bbb") + MangoDatabase.create_index(@db_name, ["name"], ddoc: "zzz") + {:ok, explain} = MangoDatabase.find(@db_name, %{"name" => "Eddie", "age" => %{"$gte" => 12}}, explain: true) + assert explain["index"]["ddoc"] == "_design/bbb" + end + + test "choose index alphabetically" do + MangoDatabase.create_index(@db_name, ["name"], ddoc: "aaa") + MangoDatabase.create_index(@db_name, ["name"], ddoc: "bbb") + MangoDatabase.create_index(@db_name, ["name"], ddoc: "zzz") + {:ok, explain} = MangoDatabase.find(@db_name, %{"name" => "Eddie", "age" => %{"$gte" => 12}}, explain: true) + assert explain["index"]["ddoc"] == "_design/aaa" + end + + test "choose index most accurate" do + MangoDatabase.create_index(@db_name, ["name", "age", "user_id"], ddoc: "aaa") + MangoDatabase.create_index(@db_name, ["name", "age"], ddoc: "bbb") + MangoDatabase.create_index(@db_name, ["name"], ddoc: "zzz") + {:ok, explain} = MangoDatabase.find(@db_name, %{"name" => "Eddie", "age" => %{"$gte" => 12}}, explain: true) + assert explain["index"]["ddoc"] == "_design/bbb" + end + + test "choose index most accurate in memory selector" do + MangoDatabase.create_index(@db_name, ["name", "location", "user_id"], ddoc: "aaa") + MangoDatabase.create_index(@db_name, ["name", "age", "user_id"], ddoc: "bbb") + MangoDatabase.create_index(@db_name, ["name"], ddoc: "zzz") + {:ok, explain} = MangoDatabase.find(@db_name, %{"name" => "Eddie", "number" => %{"$lte" => 12}}, explain: true) + assert explain["index"]["ddoc"] == "_design/zzz" + end + + test "warn on full db scan" do + selector = %{"not_indexed" => "foo"} + {:ok, explain} = MangoDatabase.find(@db_name, selector, explain: true, return_raw: true) + assert explain["index"]["type"] == "special" + {:ok, resp} = MangoDatabase.find(@db_name, selector, return_raw: true) + assert resp["warning"] == "No matching index found, create an index to optimize query time." + end + + test "chooses idxA" do + MangoDatabase.save_docs(@db_name, @docs2) + MangoDatabase.create_index(@db_name, ["a", "b", "c"]) + MangoDatabase.create_index(@db_name, ["a", "d", "e"]) + {:ok, explain} = MangoDatabase.find(@db_name, + %{"a" => %{"$gt" => 0}, "b" => %{"$gt" => 0}, "c" => %{"$gt" => 0}}, explain: true + ) + assert explain["index"]["def"]["fields"] == [%{"a" => "asc"}, %{"b" => "asc"}, %{"c" => "asc"}] + end + + test "can query with range on secondary column" do + MangoDatabase.create_index(@db_name, ["age", "name"], ddoc: "bbb") + selector = %{"age" => 10, "name" => %{"$gte" => 0}} + {:ok, docs} = MangoDatabase.find(@db_name, selector) + assert length(docs) == 1 + {:ok, explain} = MangoDatabase.find(@db_name, selector, explain: true) + assert explain["index"]["ddoc"] == "_design/bbb" + assert explain["mrargs"]["end_key"] == [10, ""] + end + + # all documents contain an _id and _rev field they + # should not be used to restrict indexes based on the + # fields required by the selector + test "choose index with id" do + MangoDatabase.create_index(@db_name, ["name", "_id"], ddoc: "aaa") + {:ok, explain} = MangoDatabase.find(@db_name, %{"name" => "Eddie"}, explain: true) + assert explain["index"]["ddoc"] == "_design/aaa" + end + + test "choose index with rev" do + MangoDatabase.create_index(@db_name, ["name", "_rev"], ddoc: "aaa") + {:ok, explain} = MangoDatabase.find(@db_name, %{"name" => "Eddie"}, explain: true) + assert explain["index"]["ddoc"] == "_design/aaa" + end +end From 13c88dc714d205b8bd9a9078d0b09cad19106f79 Mon Sep 17 00:00:00 2001 From: Alba Herrerias Date: Mon, 24 Nov 2025 15:02:45 +0000 Subject: [PATCH 2/2] Deprecate 12-use-correct-index-test.py --- src/mango/test/12-use-correct-index-test.py | 133 -------------------- 1 file changed, 133 deletions(-) delete mode 100644 src/mango/test/12-use-correct-index-test.py diff --git a/src/mango/test/12-use-correct-index-test.py b/src/mango/test/12-use-correct-index-test.py deleted file mode 100644 index 176835abf1..0000000000 --- a/src/mango/test/12-use-correct-index-test.py +++ /dev/null @@ -1,133 +0,0 @@ -# Licensed under the Apache License, Version 2.0 (the "License"); you may not -# use this file except in compliance with the License. You may obtain a copy of -# the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT -# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the -# License for the specific language governing permissions and limitations under -# the License. - -import mango -import copy - -DOCS = [ - {"_id": "_design/my-design-doc"}, - { - "_id": "54af50626de419f5109c962f", - "user_id": 0, - "age": 10, - "name": "Jimi", - "location": "UK", - "number": 4, - }, - { - "_id": "54af50622071121b25402dc3", - "user_id": 1, - "age": 12, - "name": "Eddie", - "location": "ZAR", - "number": 2, - }, - { - "_id": "54af50622071121b25402dc6", - "user_id": 1, - "age": 6, - "name": "Harry", - "location": "US", - "number": 8, - }, - { - "_id": "54af50622071121b25402dc9", - "name": "Eddie", - "occupation": "engineer", - "number": 7, - }, -] - - -class ChooseCorrectIndexForDocs(mango.DbPerClass): - def setUp(self): - super().setUp(db_per_test=True) - self.db.save_docs(copy.deepcopy(DOCS)) - - def test_choose_index_with_one_field_in_index(self): - self.db.create_index(["name", "age", "user_id"], ddoc="aaa") - self.db.create_index(["name"], ddoc="zzz") - explain = self.db.find({"name": "Eddie"}, explain=True) - self.assertEqual(explain["index"]["ddoc"], "_design/zzz") - - def test_choose_index_with_two(self): - self.db.create_index(["name", "age", "user_id"], ddoc="aaa") - self.db.create_index(["name", "age"], ddoc="bbb") - self.db.create_index(["name"], ddoc="zzz") - explain = self.db.find({"name": "Eddie", "age": {"$gte": 12}}, explain=True) - self.assertEqual(explain["index"]["ddoc"], "_design/bbb") - - def test_choose_index_alphabetically(self): - self.db.create_index(["name"], ddoc="aaa") - self.db.create_index(["name"], ddoc="bbb") - self.db.create_index(["name"], ddoc="zzz") - explain = self.db.find({"name": "Eddie", "age": {"$gte": 12}}, explain=True) - self.assertEqual(explain["index"]["ddoc"], "_design/aaa") - - def test_choose_index_most_accurate(self): - self.db.create_index(["name", "age", "user_id"], ddoc="aaa") - self.db.create_index(["name", "age"], ddoc="bbb") - self.db.create_index(["name"], ddoc="zzz") - explain = self.db.find({"name": "Eddie", "age": {"$gte": 12}}, explain=True) - self.assertEqual(explain["index"]["ddoc"], "_design/bbb") - - def test_choose_index_most_accurate_in_memory_selector(self): - self.db.create_index(["name", "location", "user_id"], ddoc="aaa") - self.db.create_index(["name", "age", "user_id"], ddoc="bbb") - self.db.create_index(["name"], ddoc="zzz") - explain = self.db.find({"name": "Eddie", "number": {"$lte": 12}}, explain=True) - self.assertEqual(explain["index"]["ddoc"], "_design/zzz") - - def test_warn_on_full_db_scan(self): - selector = {"not_indexed": "foo"} - explain_resp = self.db.find(selector, explain=True, return_raw=True) - self.assertEqual(explain_resp["index"]["type"], "special") - resp = self.db.find(selector, return_raw=True) - self.assertEqual( - resp["warning"].split("\n")[0].lower(), - "no matching index found, create an index to optimize query time.", - ) - - def test_chooses_idxA(self): - DOCS2 = [{"a": 1, "b": 1, "c": 1}, {"a": 1000, "d": 1000, "e": 1000}] - self.db.save_docs(copy.deepcopy(DOCS2)) - self.db.create_index(["a", "b", "c"]) - self.db.create_index(["a", "d", "e"]) - explain = self.db.find( - {"a": {"$gt": 0}, "b": {"$gt": 0}, "c": {"$gt": 0}}, explain=True - ) - self.assertEqual( - explain["index"]["def"]["fields"], - [{"a": "asc"}, {"b": "asc"}, {"c": "asc"}], - ) - - def test_can_query_with_range_on_secondary_column(self): - self.db.create_index(["age", "name"], ddoc="bbb") - selector = {"age": 10, "name": {"$gte": 0}} - docs = self.db.find(selector) - self.assertEqual(len(docs), 1) - explain = self.db.find(selector, explain=True) - self.assertEqual(explain["index"]["ddoc"], "_design/bbb") - self.assertEqual(explain["mrargs"]["end_key"], [10, ""]) - - # all documents contain an _id and _rev field they - # should not be used to restrict indexes based on the - # fields required by the selector - def test_choose_index_with_id(self): - self.db.create_index(["name", "_id"], ddoc="aaa") - explain = self.db.find({"name": "Eddie"}, explain=True) - self.assertEqual(explain["index"]["ddoc"], "_design/aaa") - - def test_choose_index_with_rev(self): - self.db.create_index(["name", "_rev"], ddoc="aaa") - explain = self.db.find({"name": "Eddie"}, explain=True) - self.assertEqual(explain["index"]["ddoc"], "_design/aaa")