def test_limit_skip_index(self): fields = ["field1"] ret = self.db.create_index(fields, name="idx_01") assert ret is True fields = ["field2"] ret = self.db.create_index(fields, name="idx_02") assert ret is True fields = ["field3"] ret = self.db.create_index(fields, name="idx_03") assert ret is True skip_add = 0 if mango.has_text_service(): skip_add = 1 assert len(self.db.list_indexes(limit=2)) == 2 assert len(self.db.list_indexes(limit=5, skip=4)) == 2 + skip_add assert len(self.db.list_indexes(skip=5)) == 1 + skip_add assert len(self.db.list_indexes(skip=6)) == 0 + skip_add assert len(self.db.list_indexes(skip=100)) == 0 assert len(self.db.list_indexes(limit=10000000)) == 6 + skip_add try: self.db.list_indexes(skip=-1) except Exception, e: assert e.response.status_code == 500
def test_limit_skip_index(self): fields = ["field1"] ret = self.db.create_index(fields, name="idx_01") assert ret is True fields = ["field2"] ret = self.db.create_index(fields, name="idx_02") assert ret is True fields = ["field3"] ret = self.db.create_index(fields, name="idx_03") assert ret is True skip_add = 0 if mango.has_text_service(): skip_add = 1 assert len(self.db.list_indexes(limit=2)) == 2 assert len(self.db.list_indexes(limit=5,skip=4)) == 2 + skip_add assert len(self.db.list_indexes(skip=5)) == 1 + skip_add assert len(self.db.list_indexes(skip=6)) == 0 + skip_add assert len(self.db.list_indexes(skip=100)) == 0 assert len(self.db.list_indexes(limit=10000000)) == 6 + skip_add try: self.db.list_indexes(skip=-1) except Exception, e: assert e.response.status_code == 500
def setUpClass(klass): super(DisableIndexArrayLengthsTest, klass).setUpClass() if mango.has_text_service(): klass.db.create_text_index( ddoc="disable_index_array_lengths", analyzer="keyword", index_array_lengths=False ) klass.db.create_text_index( ddoc="explicit_enable_index_array_lengths", analyzer="keyword", index_array_lengths=True )
def setUpClass(klass): super(TextIndexSelectionTests, klass).setUpClass() if mango.has_text_service(): user_docs.add_text_indexes(klass.db, {})
# as in test above, use a selector that doesn't overlap with the index # due to an explicit exists clause selector = { "company": "Pharmex", "manager": {"$exists": False} } docs = self.db.find(selector) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["company"], "Pharmex") self.assertNotIn("manager", docs[0]) resp_explain = self.db.find(selector, explain=True) self.assertEqual(resp_explain["index"]["type"], "special") @unittest.skipUnless(mango.has_text_service(), "requires text service") class TextIndexSelectionTests(mango.UserDocsTests): @classmethod def setUpClass(klass): super(TextIndexSelectionTests, klass).setUpClass() if mango.has_text_service(): user_docs.add_text_indexes(klass.db, {}) def test_with_text(self): resp = self.db.find({ "$text" : "Stephanie", "name.first": "Stephanie", "name.last": "This doesn't have to match anything." }, explain=True) self.assertEqual(resp["index"]["type"], "text")
def setUpClass(klass): super(NumStringTests, klass).setUpClass() klass.db.recreate() if mango.has_text_service(): klass.db.create_text_index()
# # 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 json import mango import unittest import user_docs import math from hypothesis import given, assume, example import hypothesis.strategies as st @unittest.skipIf(mango.has_text_service(), "text service exists") class TextIndexCheckTests(mango.DbPerClass): def test_create_text_index(self): body = json.dumps({ 'index': { }, 'type': 'text' }) resp = self.db.sess.post(self.db.path("_index"), data=body) assert resp.status_code == 503, resp @unittest.skipUnless(mango.has_text_service(), "requires text service") class BasicTextTests(mango.UserDocsTextTests): def test_simple(self):
class IndexCrudTests(mango.DbPerClass): def setUp(self): self.db.recreate() def test_bad_fields(self): bad_fields = [ None, True, False, "bing", 2.0, { "foo": "bar" }, [{ "foo": 2 }], [{ "foo": "asc", "bar": "desc" }], [{ "foo": "asc" }, { "bar": "desc" }], [""] ] for fields in bad_fields: try: self.db.create_index(fields) except Exception as e: assert e.response.status_code == 400 else: raise AssertionError("bad create index") def test_bad_types(self): bad_types = [ None, True, False, 1.5, "foo", # Future support "geo", # Future support { "foo": "bar" }, ["baz", 3.0] ] for bt in bad_types: try: self.db.create_index(["foo"], idx_type=bt) except Exception as e: assert e.response.status_code == 400, (bt, e.response.status_code) else: raise AssertionError("bad create index") def test_bad_names(self): bad_names = [True, False, 1.5, {"foo": "bar"}, [None, False]] for bn in bad_names: try: self.db.create_index(["foo"], name=bn) except Exception as e: assert e.response.status_code == 400 else: raise AssertionError("bad create index") try: self.db.create_index(["foo"], ddoc=bn) except Exception as e: assert e.response.status_code == 400 else: raise AssertionError("bad create index") def test_create_idx_01(self): fields = ["foo", "bar"] ret = self.db.create_index(fields, name="idx_01") assert ret is True for idx in self.db.list_indexes(): if idx["name"] != "idx_01": continue assert idx["def"]["fields"] == [{"foo": "asc"}, {"bar": "asc"}] return raise AssertionError("index not created") def test_create_idx_01_exists(self): fields = ["foo", "bar"] ret = self.db.create_index(fields, name="idx_01") assert ret is True ret = self.db.create_index(fields, name="idx_01") assert ret is False def test_create_idx_02(self): fields = ["baz", "foo"] ret = self.db.create_index(fields, name="idx_02") assert ret is True for idx in self.db.list_indexes(): if idx["name"] != "idx_02": continue assert idx["def"]["fields"] == [{"baz": "asc"}, {"foo": "asc"}] return raise AssertionError("index not created") def test_read_idx_doc(self): self.db.create_index(["foo", "bar"], name="idx_01") self.db.create_index(["hello", "bar"]) for idx in self.db.list_indexes(): if idx["type"] == "special": continue ddocid = idx["ddoc"] doc = self.db.open_doc(ddocid) assert doc["_id"] == ddocid info = self.db.ddoc_info(ddocid) assert info["name"] == ddocid.split('_design/')[-1] def test_delete_idx_escaped(self): self.db.create_index(["foo", "bar"], name="idx_01") pre_indexes = self.db.list_indexes() ret = self.db.create_index(["bing"], name="idx_del_1") assert ret is True for idx in self.db.list_indexes(): if idx["name"] != "idx_del_1": continue assert idx["def"]["fields"] == [{"bing": "asc"}] self.db.delete_index(idx["ddoc"].replace("/", "%2F"), idx["name"]) post_indexes = self.db.list_indexes() assert pre_indexes == post_indexes def test_delete_idx_unescaped(self): pre_indexes = self.db.list_indexes() ret = self.db.create_index(["bing"], name="idx_del_2") assert ret is True for idx in self.db.list_indexes(): if idx["name"] != "idx_del_2": continue assert idx["def"]["fields"] == [{"bing": "asc"}] self.db.delete_index(idx["ddoc"], idx["name"]) post_indexes = self.db.list_indexes() assert pre_indexes == post_indexes def test_delete_idx_no_design(self): pre_indexes = self.db.list_indexes() ret = self.db.create_index(["bing"], name="idx_del_3") assert ret is True for idx in self.db.list_indexes(): if idx["name"] != "idx_del_3": continue assert idx["def"]["fields"] == [{"bing": "asc"}] self.db.delete_index(idx["ddoc"].split("/")[-1], idx["name"]) post_indexes = self.db.list_indexes() assert pre_indexes == post_indexes def test_bulk_delete(self): fields = ["field1"] ret = self.db.create_index(fields, name="idx_01") assert ret is True fields = ["field2"] ret = self.db.create_index(fields, name="idx_02") assert ret is True fields = ["field3"] ret = self.db.create_index(fields, name="idx_03") assert ret is True docids = [] for idx in self.db.list_indexes(): if idx["ddoc"] is not None: docids.append(idx["ddoc"]) docids.append("_design/this_is_not_an_index_name") ret = self.db.bulk_delete(docids) assert ret["fail"][0]["id"] == "_design/this_is_not_an_index_name" assert len(ret["success"]) == 3 for idx in self.db.list_indexes(): assert idx["type"] != "json" assert idx["type"] != "text" def test_recreate_index(self): pre_indexes = self.db.list_indexes() for i in range(5): ret = self.db.create_index(["bing"], name="idx_recreate") assert ret is True for idx in self.db.list_indexes(): if idx["name"] != "idx_recreate": continue assert idx["def"]["fields"] == [{"bing": "asc"}] self.db.delete_index(idx["ddoc"], idx["name"]) break post_indexes = self.db.list_indexes() assert pre_indexes == post_indexes def test_delete_misisng(self): # Missing design doc try: self.db.delete_index("this_is_not_a_design_doc_id", "foo") except Exception as e: assert e.response.status_code == 404 else: raise AssertionError("bad index delete") # Missing view name ret = self.db.create_index(["fields"], name="idx_01") indexes = self.db.list_indexes() not_special = [idx for idx in indexes if idx["type"] != "special"] idx = random.choice(not_special) ddocid = idx["ddoc"].split("/")[-1] try: self.db.delete_index(ddocid, "this_is_not_an_index_name") except Exception as e: assert e.response.status_code == 404 else: raise AssertionError("bad index delete") # Bad view type try: self.db.delete_index(ddocid, idx["name"], idx_type="not_a_real_type") except Exception as e: assert e.response.status_code == 404 else: raise AssertionError("bad index delete") @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_create_text_idx(self): fields = [{ "name": "stringidx", "type": "string" }, { "name": "booleanidx", "type": "boolean" }] ret = self.db.create_text_index(fields=fields, name="text_idx_01") assert ret is True for idx in self.db.list_indexes(): if idx["name"] != "text_idx_01": continue assert idx["def"]["fields"] == [{ "stringidx": "string" }, { "booleanidx": "boolean" }] return raise AssertionError("index not created") @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_create_bad_text_idx(self): bad_fields = [ True, False, "bing", 2.0, ["foo", "bar"], [{ "name": "foo2" }], [{ "name": "foo3", "type": "garbage" }], [{ "type": "number" }], [{ "name": "age", "type": "number" }, { "name": "bad" }], [{ "name": "age", "type": "number" }, "bla"], [{ "name": "", "type": "number" }, "bla"] ] for fields in bad_fields: try: self.db.create_text_index(fields=fields) except Exception as e: assert e.response.status_code == 400 else: raise AssertionError("bad create text index") def test_limit_skip_index(self): fields = ["field1"] ret = self.db.create_index(fields, name="idx_01") assert ret is True fields = ["field2"] ret = self.db.create_index(fields, name="idx_02") assert ret is True fields = ["field3"] ret = self.db.create_index(fields, name="idx_03") assert ret is True fields = ["field4"] ret = self.db.create_index(fields, name="idx_04") assert ret is True fields = ["field5"] ret = self.db.create_index(fields, name="idx_05") assert ret is True skip_add = 0 if mango.has_text_service(): skip_add = 1 assert len(self.db.list_indexes(limit=2)) == 2 assert len(self.db.list_indexes(limit=5, skip=4)) == 2 + skip_add assert len(self.db.list_indexes(skip=5)) == 1 + skip_add assert len(self.db.list_indexes(skip=6)) == 0 + skip_add assert len(self.db.list_indexes(skip=100)) == 0 assert len(self.db.list_indexes(limit=10000000)) == 6 + skip_add try: self.db.list_indexes(skip=-1) except Exception as e: assert e.response.status_code == 500 try: self.db.list_indexes(limit=0) except Exception as e: assert e.response.status_code == 500
def setUpClass(klass): super(MultiTextIndexSelectionTests, klass).setUpClass() if mango.has_text_service(): klass.db.create_text_index(ddoc="foo", analyzer="keyword") klass.db.create_text_index(ddoc="bar", analyzer="email")
def setUpClass(klass): super(KeyTests, klass).setUpClass() klass.db.save_docs(TEST_DOCS, w=3) klass.db.create_index(["type"], ddoc="view") if mango.has_text_service(): klass.db.create_text_index(ddoc="text")
class OperatorTests: def assertUserIds(self, user_ids, docs): user_ids_returned = list(d["user_id"] for d in docs) user_ids.sort() user_ids_returned.sort() self.assertEqual(user_ids, user_ids_returned) def test_all(self): docs = self.db.find({ "manager": True, "favorites": {"$all": ["Lisp", "Python"]} }) self.assertEqual(len(docs), 4) user_ids = [2,12,9,14] self.assertUserIds(user_ids, docs) def test_all_non_array(self): docs = self.db.find({ "manager": True, "location": {"$all": ["Ohai"]} }) self.assertEqual(len(docs), 0) def test_elem_match(self): emdocs = [ { "user_id": "a", "bang": [{ "foo": 1, "bar": 2 }] }, { "user_id": "b", "bang": [{ "foo": 2, "bam": True }] } ] self.db.save_docs(emdocs, w=3) docs = self.db.find({ "_id": {"$gt": None}, "bang": {"$elemMatch": { "foo": {"$gte": 1}, "bam": True }} }) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["user_id"], "b") def test_all_match(self): amdocs = [ { "user_id": "a", "bang": [ { "foo": 1, "bar": 2 }, { "foo": 3, "bar": 4 } ] }, { "user_id": "b", "bang": [ { "foo": 1, "bar": 2 }, { "foo": 4, "bar": 4 } ] } ] self.db.save_docs(amdocs, w=3) docs = self.db.find({ "bang": {"$allMatch": { "foo": {"$mod": [2,1]}, "bar": {"$mod": [2,0]} }} }) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["user_id"], "a") def test_empty_all_match(self): amdocs = [ { "bad_doc": "a", "emptybang": [] } ] self.db.save_docs(amdocs, w=3) docs = self.db.find({ "emptybang": {"$allMatch": { "foo": {"$eq": 2} }} }) self.assertEqual(len(docs), 0) def test_in_operator_array(self): docs = self.db.find({ "manager": True, "favorites": {"$in": ["Ruby", "Python"]} }) self.assertUserIds([2,6,7,9,11,12,14], docs) def test_nin_operator_array(self): docs = self.db.find({ "manager": True, "favorites": {"$nin": ["Erlang", "Python"]} }) self.assertEqual(len(docs), 4) for doc in docs: if isinstance(doc["favorites"], list): self.assertNotIn("Erlang", doc["favorites"]) self.assertNotIn("Python", doc["favorites"]) def test_regex(self): docs = self.db.find({ "age": {"$gt": 40}, "location.state": {"$regex": "(?i)new.*"} }) self.assertEqual(len(docs), 2) self.assertUserIds([2,10], docs) def test_exists_false(self): docs = self.db.find({ "age": {"$gt": 0}, "twitter": {"$exists": False} }) user_ids = [2,3,5,6,7,8,10,11,12,14] self.assertUserIds(user_ids, docs) for d in docs: self.assertNotIn("twitter", d) def test_eq_null_does_not_include_missing(self): docs = self.db.find({ "age": {"$gt": 0}, "twitter": None }) user_ids = [9] self.assertUserIds(user_ids, docs) for d in docs: self.assertEqual(d["twitter"], None) def test_ne_includes_null_but_not_missing(self): docs = self.db.find({ "twitter": {"$ne": "notamatch"} }) user_ids = [0,1,4,9,13] self.assertUserIds(user_ids, docs) for d in docs: self.assertIn("twitter", d) def test_lt_includes_null_but_not_missing(self): docs = self.db.find({ "twitter": {"$lt": 1} }) user_ids = [9] self.assertUserIds(user_ids, docs) for d in docs: self.assertEqual(d["twitter"], None) def test_lte_includes_null_but_not_missing(self): docs = self.db.find({ "twitter": {"$lt": 1} }) user_ids = [9] self.assertUserIds(user_ids, docs) for d in docs: self.assertEqual(d["twitter"], None) def test_lte_null_includes_null_but_not_missing(self): docs = self.db.find({ "twitter": {"$lte": None} }) user_ids = [9] self.assertUserIds(user_ids, docs) for d in docs: self.assertEqual(d["twitter"], None) def test_lte_at_z_except_null_excludes_null_and_missing(self): docs = self.db.find({ "twitter": {"$and": [ {"$lte": "@z"}, {"$ne": None} ]} }) user_ids = [0,1,4,13] self.assertUserIds(user_ids, docs) for d in docs: self.assertNotEqual(d["twitter"], None) def test_range_gte_null_includes_null_but_not_missing(self): docs = self.db.find({ "twitter": {"$gte": None} }) self.assertGreater(len(docs), 0) for d in docs: self.assertIn("twitter", d) def test_exists_false_returns_missing_but_not_null(self): docs = self.db.find({ "twitter": {"$exists": False} }) self.assertGreater(len(docs), 0) for d in docs: self.assertNotIn("twitter", d) @unittest.skipUnless(not mango.has_text_service(), "text indexes do not support range queries across type boundaries") def test_lte_respsects_unicode_collation(self): docs = self.db.find({ "ordered": {"$lte": "a"} }) user_ids = [7,8,9,10,11,12] self.assertUserIds(user_ids, docs) @unittest.skipUnless(not mango.has_text_service(), "text indexes do not support range queries across type boundaries") def test_gte_respsects_unicode_collation(self): docs = self.db.find({ "ordered": {"$gte": "a"} }) user_ids = [12,13,14] self.assertUserIds(user_ids, docs)
class IndexSelectionTests(mango.UserDocsTests): @classmethod def setUpClass(klass): super(IndexSelectionTests, klass).setUpClass() if mango.has_text_service(): user_docs.add_text_indexes(klass.db, {}) def test_basic(self): resp = self.db.find({"name.last": "A last name"}, explain=True) assert resp["index"]["type"] == "json" def test_with_and(self): resp = self.db.find( { "name.first": "Stephanie", "name.last": "This doesn't have to match anything." }, explain=True) assert resp["index"]["type"] == "json" @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_with_text(self): resp = self.db.find( { "$text": "Stephanie", "name.first": "Stephanie", "name.last": "This doesn't have to match anything." }, explain=True) assert resp["index"]["type"] == "text" @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_no_view_index(self): resp = self.db.find({"name.first": "Ohai!"}, explain=True) assert resp["index"]["type"] == "text" @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_with_or(self): resp = self.db.find( { "$or": [{ "name.first": "Stephanie" }, { "name.last": "This doesn't have to match anything." }] }, explain=True) assert resp["index"]["type"] == "text" def test_use_most_columns(self): # ddoc id for the age index ddocid = "_design/ad3d537c03cd7c6a43cf8dff66ef70ea54c2b40f" resp = self.db.find( { "name.first": "Stephanie", "name.last": "Something or other", "age": { "$gt": 1 } }, explain=True) assert resp["index"]["ddoc"] != "_design/" + ddocid resp = self.db.find( { "name.first": "Stephanie", "name.last": "Something or other", "age": { "$gt": 1 } }, use_index=ddocid, explain=True) assert resp["index"]["ddoc"] == ddocid def test_use_most_columns(self): # ddoc id for the age index ddocid = "_design/ad3d537c03cd7c6a43cf8dff66ef70ea54c2b40f" try: self.db.find({}, use_index=ddocid) except Exception, e: assert e.response.status_code == 400 else:
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_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) @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_text_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) @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_text_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) @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_text_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) @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_text_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") @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_text_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") @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_text_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)
class IndexSelectionTests(mango.UserDocsTests): @classmethod def setUpClass(klass): super(IndexSelectionTests, klass).setUpClass() if mango.has_text_service(): user_docs.add_text_indexes(klass.db, {}) def test_basic(self): resp = self.db.find({"name.last": "A last name"}, explain=True) assert resp["index"]["type"] == "json" def test_with_and(self): resp = self.db.find( { "name.first": "Stephanie", "name.last": "This doesn't have to match anything." }, explain=True) assert resp["index"]["type"] == "json" @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_with_text(self): resp = self.db.find( { "$text": "Stephanie", "name.first": "Stephanie", "name.last": "This doesn't have to match anything." }, explain=True) assert resp["index"]["type"] == "text" @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_no_view_index(self): resp = self.db.find({"name.first": "Ohai!"}, explain=True) assert resp["index"]["type"] == "text" @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_with_or(self): resp = self.db.find( { "$or": [{ "name.first": "Stephanie" }, { "name.last": "This doesn't have to match anything." }] }, explain=True) assert resp["index"]["type"] == "text" def test_use_most_columns(self): # ddoc id for the age index ddocid = "_design/ad3d537c03cd7c6a43cf8dff66ef70ea54c2b40f" resp = self.db.find( { "name.first": "Stephanie", "name.last": "Something or other", "age": { "$gt": 1 } }, explain=True) assert resp["index"]["ddoc"] != "_design/" + ddocid resp = self.db.find( { "name.first": "Stephanie", "name.last": "Something or other", "age": { "$gt": 1 } }, use_index=ddocid, explain=True) assert resp["index"]["ddoc"] == ddocid # This doc will not be saved given the new ddoc validation code # in couch_mrview def test_manual_bad_view_idx01(self): design_doc = { "_id": "_design/bad_view_index", "language": "query", "views": { "queryidx1": { "map": { "fields": { "age": "asc" } }, "reduce": "_count", "options": { "def": { "fields": [{ "age": "asc" }] }, "w": 2 } } }, "views": { "views001": { "map": "function(employee){if(employee.training)" + "{emit(employee.number, employee.training);}}" } } } with self.assertRaises(KeyError): self.db.save_doc(design_doc) @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_manual_bad_text_idx(self): design_doc = { "_id": "_design/bad_text_index", "language": "query", "indexes": { "text_index": { "default_analyzer": "keyword", "default_field": {}, "selector": {}, "fields": "all_fields", "analyzer": { "name": "perfield", "default": "keyword", "fields": { "$default": "standard" } } } }, "indexes": { "st_index": { "analyzer": "standard", "index": "function(doc){\n index(\"st_index\", doc.geometry);\n}" } } } self.db.save_doc(design_doc) docs = self.db.find({"age": 48}) assert len(docs) == 1 assert docs[0]["name"]["first"] == "Stephanie" assert docs[0]["age"] == 48
# 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 limit_docs import unittest @unittest.skipUnless(mango.has_text_service(), "requires text service") class LimitTests(mango.LimitDocsTextTests): def test_limit_field(self): q = {"$or": [{"user_id": {"$lt": 10}}, {"filtered_array.[]": 1}]} docs = self.db.find(q, limit=10) assert len(docs) == 8 for d in docs: assert d["user_id"] < 10 def test_limit_field2(self): q = {"$or": [{"user_id": {"$lt": 20}}, {"filtered_array.[]": 1}]} docs = self.db.find(q, limit=10) assert len(docs) == 10 for d in docs: assert d["user_id"] < 20
class IndexSelectionTests(mango.UserDocsTests): @classmethod def setUpClass(klass): super(IndexSelectionTests, klass).setUpClass() if mango.has_text_service(): user_docs.add_text_indexes(klass.db, {}) def test_basic(self): resp = self.db.find({"age": 123}, explain=True) self.assertEqual(resp["index"]["type"], "json") def test_with_and(self): resp = self.db.find( { "name.first": "Stephanie", "name.last": "This doesn't have to match anything." }, explain=True) self.assertEqual(resp["index"]["type"], "json") @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_with_text(self): resp = self.db.find( { "$text": "Stephanie", "name.first": "Stephanie", "name.last": "This doesn't have to match anything." }, explain=True) self.assertEqual(resp["index"]["type"], "text") @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_no_view_index(self): resp = self.db.find({"name.first": "Ohai!"}, explain=True) self.assertEqual(resp["index"]["type"], "text") @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_with_or(self): resp = self.db.find( { "$or": [{ "name.first": "Stephanie" }, { "name.last": "This doesn't have to match anything." }] }, explain=True) self.assertEqual(resp["index"]["type"], "text") def test_use_most_columns(self): # ddoc id for the age index ddocid = "_design/ad3d537c03cd7c6a43cf8dff66ef70ea54c2b40f" resp = self.db.find( { "name.first": "Stephanie", "name.last": "Something or other", "age": { "$gt": 1 } }, explain=True) self.assertNotEqual(resp["index"]["ddoc"], "_design/" + ddocid) resp = self.db.find( { "name.first": "Stephanie", "name.last": "Something or other", "age": { "$gt": 1 } }, use_index=ddocid, explain=True) self.assertEqual(resp["index"]["ddoc"], ddocid) def test_no_valid_sort_index(self): try: self.db.find({"_id": { "$gt": None }}, sort=["name"], return_raw=True) except Exception as e: self.assertEqual(e.response.status_code, 400) else: raise AssertionError("bad find") def test_invalid_use_index(self): # ddoc id for the age index ddocid = "_design/ad3d537c03cd7c6a43cf8dff66ef70ea54c2b40f" try: self.db.find({}, use_index=ddocid) except Exception as e: self.assertEqual(e.response.status_code, 400) else: raise AssertionError("bad find") def test_uses_all_docs_when_fields_do_not_match_selector(self): # index exists on ["company", "manager"] but not ["company"] # so we should fall back to all docs (so we include docs # with no "manager" field) selector = {"company": "Pharmex"} docs = self.db.find(selector) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["company"], "Pharmex") self.assertNotIn("manager", docs[0]) resp_explain = self.db.find(selector, explain=True) self.assertEqual(resp_explain["index"]["type"], "special") def test_uses_all_docs_when_selector_doesnt_require_fields_to_exist(self): # as in test above, use a selector that doesn't overlap with the index # due to an explicit exists clause selector = {"company": "Pharmex", "manager": {"$exists": False}} docs = self.db.find(selector) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["company"], "Pharmex") self.assertNotIn("manager", docs[0]) resp_explain = self.db.find(selector, explain=True) self.assertEqual(resp_explain["index"]["type"], "special") def test_uses_index_when_no_range_or_equals(self): # index on ["manager"] should be valid because # selector requires "manager" to exist. The # selector doesn't narrow the keyrange so it's # a full index scan selector = {"manager": {"$exists": True}} docs = self.db.find(selector) self.assertEqual(len(docs), 14) resp_explain = self.db.find(selector, explain=True) self.assertEqual(resp_explain["index"]["type"], "json") def test_reject_use_index_invalid_fields(self): # index on ["company","manager"] which should not be valid ddocid = "_design/a0c425a60cf3c3c09e3c537c9ef20059dcef9198" selector = {"company": "Pharmex"} try: self.db.find(selector, use_index=ddocid) except Exception as e: self.assertEqual(e.response.status_code, 400) else: raise AssertionError("did not reject bad use_index") def test_reject_use_index_sort_order(self): # index on ["company","manager"] which should not be valid ddocid = "_design/a0c425a60cf3c3c09e3c537c9ef20059dcef9198" selector = {"company": {"$gt": None}, "manager": {"$gt": None}} try: self.db.find(selector, use_index=ddocid, sort=[{ "manager": "desc" }]) except Exception as e: self.assertEqual(e.response.status_code, 400) else: raise AssertionError("did not reject bad use_index") # This doc will not be saved given the new ddoc validation code # in couch_mrview def test_manual_bad_view_idx01(self): design_doc = { "_id": "_design/bad_view_index", "language": "query", "views": { "queryidx1": { "map": { "fields": { "age": "asc" } }, "reduce": "_count", "options": { "def": { "fields": [{ "age": "asc" }] }, "w": 2 } } }, "views": { "views001": { "map": "function(employee){if(employee.training)" + "{emit(employee.number, employee.training);}}" } } } with self.assertRaises(KeyError): self.db.save_doc(design_doc) @unittest.skipUnless(mango.has_text_service(), "requires text service") def test_manual_bad_text_idx(self): design_doc = { "_id": "_design/bad_text_index", "language": "query", "indexes": { "text_index": { "default_analyzer": "keyword", "default_field": {}, "selector": {}, "fields": "all_fields", "analyzer": { "name": "perfield", "default": "keyword", "fields": { "$default": "standard" } } } }, "indexes": { "st_index": { "analyzer": "standard", "index": "function(doc){\n index(\"st_index\", doc.geometry);\n}" } } } self.db.save_doc(design_doc) docs = self.db.find({"age": 48}) self.assertEqual(len(docs), 1) self.assertEqual(docs[0]["name"]["first"], "Stephanie") self.assertEqual(docs[0]["age"], 48)