blob: ed5eb3847711c1474e27bb8ab7f83a1ab5f3a3da [file] [log] [blame]
# 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 unittest
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), 3)
user_ids = [2, 12, 9]
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)
@unittest.skipUnless(
not mango.has_text_service(),
"text indexes do not support the $keyMapMatch operator",
)
def test_keymap_match(self):
amdocs = [
{"foo": {"aa": "bar", "bb": "bang"}},
{"foo": {"cc": "bar", "bb": "bang"}},
]
self.db.save_docs(amdocs, w=3)
docs = self.db.find({"foo": {"$keyMapMatch": {"$eq": "aa"}}})
self.assertEqual(len(docs), 1)
def test_in_operator_array(self):
docs = self.db.find({"manager": True, "favorites": {"$in": ["Ruby", "Python"]}})
self.assertUserIds([2, 6, 7, 9, 11, 12], 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)
# ideally this work be consistent across index types but, alas, it is not
@unittest.skipUnless(
not mango.has_text_service(),
"text indexes do not support range queries across type boundaries",
)
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)
@unittest.skipUnless(
not mango.has_text_service(),
"text indexes do not support range queries across type boundaries",
)
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 OperatorJSONTests(mango.UserDocsTests, OperatorTests):
pass
@unittest.skipUnless(mango.has_text_service(), "requires text service")
class OperatorTextTests(mango.UserDocsTextTests, OperatorTests):
pass
class OperatorAllDocsTests(mango.UserDocsTestsNoIndexes, OperatorTests):
def test_range_id_eq(self):
doc_id = "8e1c90c0-ac18-4832-8081-40d14325bde0"
r = self.db.find({"_id": doc_id}, explain=True, return_raw=True)
self.assertEqual(r["mrargs"]["end_key"], doc_id)
self.assertEqual(r["mrargs"]["start_key"], doc_id)