| # 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 copy |
| import mango |
| import unittest |
| |
| DOCS = [ |
| {"_id": "100", "name": "Jimi", "location": "AUS", "user_id": 1, "same": "value"}, |
| {"_id": "200", "name": "Eddie", "location": "BRA", "user_id": 2, "same": "value"}, |
| {"_id": "300", "name": "Harry", "location": "CAN", "user_id": 3, "same": "value"}, |
| {"_id": "400", "name": "Eddie", "location": "DEN", "user_id": 4, "same": "value"}, |
| {"_id": "500", "name": "Jones", "location": "ETH", "user_id": 5, "same": "value"}, |
| { |
| "_id": "600", |
| "name": "Winnifried", |
| "location": "FRA", |
| "user_id": 6, |
| "same": "value", |
| }, |
| {"_id": "700", "name": "Marilyn", "location": "GHA", "user_id": 7, "same": "value"}, |
| {"_id": "800", "name": "Sandra", "location": "ZAR", "user_id": 8, "same": "value"}, |
| ] |
| |
| oldschoolnoselectorddoc = { |
| "_id": "_design/oldschoolnoselector", |
| "language": "query", |
| "views": { |
| "oldschoolnoselector": { |
| "map": {"fields": {"location": "asc"}}, |
| "reduce": "_count", |
| "options": {"def": {"fields": ["location"]}}, |
| } |
| }, |
| } |
| |
| oldschoolddoc = { |
| "_id": "_design/oldschool", |
| "language": "query", |
| "views": { |
| "oldschool": { |
| "map": { |
| "fields": {"location": "asc"}, |
| "selector": {"location": {"$gte": "FRA"}}, |
| }, |
| "reduce": "_count", |
| "options": {"def": {"fields": ["location"]}}, |
| } |
| }, |
| } |
| |
| oldschoolddoctext = { |
| "_id": "_design/oldschooltext", |
| "language": "query", |
| "indexes": { |
| "oldschooltext": { |
| "index": { |
| "default_analyzer": "keyword", |
| "default_field": {}, |
| "selector": {"location": {"$gte": "FRA"}}, |
| "fields": [{"name": "location", "type": "string"}], |
| "index_array_lengths": True, |
| }, |
| "analyzer": { |
| "name": "perfield", |
| "default": "keyword", |
| "fields": {"$default": "standard"}, |
| }, |
| } |
| }, |
| } |
| |
| |
| class IndexSelectorJson(mango.DbPerClass): |
| def setUp(self): |
| self.db.recreate() |
| self.db.save_docs(copy.deepcopy(DOCS)) |
| |
| def test_saves_partial_filter_selector_in_index(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_index(["location"], partial_filter_selector=selector) |
| indexes = self.db.list_indexes() |
| self.assertEqual(indexes[1]["def"]["partial_filter_selector"], selector) |
| |
| def test_partial_filter_only_in_return_if_not_default(self): |
| self.db.create_index(["location"]) |
| index = self.db.list_indexes()[1] |
| self.assertEqual("partial_filter_selector" in index["def"], False) |
| |
| def test_saves_selector_in_index_throws(self): |
| selector = {"location": {"$gte": "FRA"}} |
| try: |
| self.db.create_index(["location"], selector=selector) |
| except Exception as e: |
| assert e.response.status_code == 400 |
| else: |
| raise AssertionError("bad index creation") |
| |
| def test_uses_partial_index_for_query_selector(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_index( |
| ["location"], |
| partial_filter_selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| resp = self.db.find(selector, explain=True, use_index="Selected") |
| self.assertEqual(resp["index"]["name"], "Selected") |
| docs = self.db.find(selector, use_index="Selected") |
| self.assertEqual(len(docs), 3) |
| |
| def test_uses_partial_index_with_different_selector(self): |
| selector = {"location": {"$gte": "FRA"}} |
| selector2 = {"location": {"$gte": "A"}} |
| self.db.create_index( |
| ["location"], |
| partial_filter_selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| resp = self.db.find(selector2, explain=True, use_index="Selected") |
| self.assertEqual(resp["index"]["name"], "Selected") |
| docs = self.db.find(selector2, use_index="Selected") |
| self.assertEqual(len(docs), 3) |
| |
| def test_doesnot_use_selector_when_not_specified(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_index( |
| ["location"], |
| partial_filter_selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| resp = self.db.find(selector, explain=True) |
| self.assertEqual(resp["index"]["name"], "_all_docs") |
| |
| def test_doesnot_use_selector_when_not_specified_with_index(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_index( |
| ["location"], |
| partial_filter_selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| self.db.create_index(["location"], name="NotSelected") |
| resp = self.db.find(selector, explain=True) |
| self.assertEqual(resp["index"]["name"], "NotSelected") |
| |
| def test_old_selector_with_no_selector_still_supported(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.save_doc(oldschoolnoselectorddoc) |
| resp = self.db.find(selector, explain=True, use_index="oldschoolnoselector") |
| self.assertEqual(resp["index"]["name"], "oldschoolnoselector") |
| docs = self.db.find(selector, use_index="oldschoolnoselector") |
| self.assertEqual(len(docs), 3) |
| |
| def test_old_selector_still_supported(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.save_doc(oldschoolddoc) |
| resp = self.db.find(selector, explain=True, use_index="oldschool") |
| self.assertEqual(resp["index"]["name"], "oldschool") |
| docs = self.db.find(selector, use_index="oldschool") |
| self.assertEqual(len(docs), 3) |
| |
| def test_uses_partial_index_with_non_indexable_selector(self): |
| partial_selector = {"location": {"$gte": "FRA"}} |
| selector = {"location": {"$exists": True}} |
| self.db.create_index( |
| ["location"], |
| partial_filter_selector=partial_selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| resp = self.db.find(selector, explain=True, use_index="Selected") |
| self.assertEqual(resp["index"]["name"], "Selected") |
| docs = self.db.find(selector, use_index="Selected") |
| self.assertEqual(len(docs), 3) |
| |
| |
| @unittest.skipUnless(mango.has_text_service(), "requires text service") |
| class IndexSelectorText(mango.DbPerClass): |
| def setUp(self): |
| self.db.recreate() |
| self.db.save_docs(copy.deepcopy(DOCS)) |
| |
| def test_saves_partialfilterselector_in_index(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_text_index( |
| fields=[{"name": "location", "type": "string"}], |
| partial_filter_selector=selector, |
| ) |
| indexes = self.db.list_indexes() |
| self.assertEqual(indexes[1]["def"]["partial_filter_selector"], selector) |
| |
| def test_uses_partial_index_for_query_selector(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_text_index( |
| fields=[{"name": "location", "type": "string"}], |
| partial_filter_selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| resp = self.db.find(selector, explain=True, use_index="Selected") |
| self.assertEqual(resp["index"]["name"], "Selected") |
| docs = self.db.find(selector, use_index="Selected", fields=["_id", "location"]) |
| self.assertEqual(len(docs), 3) |
| |
| def test_uses_partial_index_with_different_selector(self): |
| selector = {"location": {"$gte": "FRA"}} |
| selector2 = {"location": {"$gte": "A"}} |
| self.db.create_text_index( |
| fields=[{"name": "location", "type": "string"}], |
| partial_filter_selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| resp = self.db.find(selector2, explain=True, use_index="Selected") |
| self.assertEqual(resp["index"]["name"], "Selected") |
| docs = self.db.find(selector2, use_index="Selected") |
| self.assertEqual(len(docs), 3) |
| |
| def test_doesnot_use_selector_when_not_specified(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_text_index( |
| fields=[{"name": "location", "type": "string"}], |
| partial_filter_selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| resp = self.db.find(selector, explain=True) |
| self.assertEqual(resp["index"]["name"], "_all_docs") |
| |
| def test_doesnot_use_selector_when_not_specified_with_index(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_text_index( |
| fields=[{"name": "location", "type": "string"}], |
| partial_filter_selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| self.db.create_text_index( |
| fields=[{"name": "location", "type": "string"}], name="NotSelected" |
| ) |
| resp = self.db.find(selector, explain=True) |
| self.assertEqual(resp["index"]["name"], "NotSelected") |
| |
| def test_old_selector_still_supported(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.save_doc(oldschoolddoctext) |
| resp = self.db.find(selector, explain=True, use_index="oldschooltext") |
| self.assertEqual(resp["index"]["name"], "oldschooltext") |
| docs = self.db.find(selector, use_index="oldschooltext") |
| self.assertEqual(len(docs), 3) |
| |
| def test_old_selector_still_supported_via_api(self): |
| selector = {"location": {"$gte": "FRA"}} |
| self.db.create_text_index( |
| fields=[{"name": "location", "type": "string"}], |
| selector=selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| docs = self.db.find({"location": {"$exists": True}}, use_index="Selected") |
| self.assertEqual(len(docs), 3) |
| |
| def test_partial_filter_only_in_return_if_not_default(self): |
| self.db.create_text_index(fields=[{"name": "location", "type": "string"}]) |
| index = self.db.list_indexes()[1] |
| self.assertEqual("partial_filter_selector" in index["def"], False) |
| |
| def test_uses_partial_index_with_non_indexable_selector(self): |
| partial_selector = {"location": {"$gte": "FRA"}} |
| selector = {"location": {"$exists": True}} |
| self.db.create_text_index( |
| ["location"], |
| partial_filter_selector=partial_selector, |
| ddoc="Selected", |
| name="Selected", |
| ) |
| resp = self.db.find(selector, explain=True, use_index="Selected") |
| self.assertEqual(resp["index"]["name"], "Selected") |
| docs = self.db.find(selector, use_index="Selected") |
| self.assertEqual(len(docs), 3) |