From 165fe03352c93e0a4f895ba1c9ecf07683c91887 Mon Sep 17 00:00:00 2001 From: Tony Sun Date: Tue, 3 Oct 2017 17:40:24 -0700 Subject: fix exists false when field is explicitly defined When users explicitly defined a text index's fields, and used $exists with false, we tag false when constructing the query. This led to a function clause for indexable_fields since we did not account for it. This fix patches that up, but note that we don't care about the false value itself since we only care about fields. --- src/mango/src/mango_idx_text.erl | 3 ++ src/mango/test/07-text-custom-field-list-test.py | 50 ++++++++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/src/mango/src/mango_idx_text.erl b/src/mango/src/mango_idx_text.erl index 1d5ae9bad..369e2cd08 100644 --- a/src/mango/src/mango_idx_text.erl +++ b/src/mango/src/mango_idx_text.erl @@ -329,6 +329,9 @@ indexable_fields(Fields, {op_or, Args}) when is_list(Args) -> indexable_fields(Fields, {op_not, {ExistsQuery, Arg}}) when is_tuple(Arg) -> Fields0 = indexable_fields(Fields, ExistsQuery), indexable_fields(Fields0, Arg); +% forces "$exists" : false to use _all_docs +indexable_fields(Fields, {op_not, {ExistsQuery, false}}) -> + []; indexable_fields(Fields, {op_insert, Arg}) when is_binary(Arg) -> Fields; diff --git a/src/mango/test/07-text-custom-field-list-test.py b/src/mango/test/07-text-custom-field-list-test.py index a43e33003..9bfe07598 100644 --- a/src/mango/test/07-text-custom-field-list-test.py +++ b/src/mango/test/07-text-custom-field-list-test.py @@ -12,6 +12,7 @@ import mango import unittest +import user_docs @unittest.skipUnless(mango.has_text_service(), "requires text service") @@ -160,3 +161,52 @@ class CustomFieldsTest(mango.UserDocsTextTests): }) assert len(docs) == 1 assert docs[0]["user_id"] == 10 + +@unittest.skipUnless(mango.has_text_service(), "requires text service") +class CustomFieldsExistsTest(mango.UserDocsTextTests): + + FIELDS = [ + {"name": "exists_field", "type": "string"}, + {"name": "exists_array.[]", "type": "string"}, + {"name": "exists_object.should", "type": "string"}, + {"name": "twitter", "type": "string"} + ] + + def test_exists_field(self): + docs = self.db.find({"exists_field": {"$exists": True}}) + self.assertEqual(len(docs), 2) + for d in docs: + self.assertIn(d["user_id"], (7, 8)) + + docs = self.db.find({"exists_field": {"$exists": False}}) + self.assertEqual(len(docs), len(user_docs.DOCS) - 2) + for d in docs: + self.assertNotIn(d["user_id"], (7, 8)) + + def test_exists_array(self): + docs = self.db.find({"exists_array": {"$exists": True}}) + self.assertEqual(len(docs), 2) + for d in docs: + self.assertIn(d["user_id"], (9, 10)) + + docs = self.db.find({"exists_array": {"$exists": False}}) + self.assertEqual(len(docs), len(user_docs.DOCS) - 2) + for d in docs: + self.assertNotIn(d["user_id"], (9, 10)) + + def test_exists_object_member(self): + docs = self.db.find({"exists_object.should": {"$exists": True}}) + self.assertEqual(len(docs), 1) + self.assertEqual(docs[0]["user_id"], 11) + + docs = self.db.find({"exists_object.should": {"$exists": False}}) + self.assertEqual(len(docs), len(user_docs.DOCS) - 1) + for d in docs: + self.assertNotEqual(d["user_id"], 11) + + def test_exists_false_same_as_views(self): + docs = self.db.find({ + "twitter": {"$exists": False} + }) + for d in docs: + self.assertNotIn(d["user_id"], (0, 1, 4, 13)) -- cgit v1.2.1