Handle extra <<>> when elemMatch normalizes selector When $elemMatch is applied to non-objects such as: {"results":{"$elemMatch": {"$gte": 80, "$lt": 85}}}, our normalizer modifies the selector to include <<>>. This causes issues for our path_str and match functions. This fix addresses those issues by removing the <<>> from the selector and also not adding a period when a Part is <<>>.
BugzId: 44817 Project: http://git-wip-us.apache.org/repos/asf/couchdb-mango/repo Commit: http://git-wip-us.apache.org/repos/asf/couchdb-mango/commit/10fcac2b Tree: http://git-wip-us.apache.org/repos/asf/couchdb-mango/tree/10fcac2b Diff: http://git-wip-us.apache.org/repos/asf/couchdb-mango/diff/10fcac2b Branch: refs/heads/2787-merge-repos Commit: 10fcac2be08f22395935bd938d5dccf5e8d71ac9 Parents: ca5ff7b Author: Tony Sun <tony....@cloudant.com> Authored: Tue Aug 25 11:26:50 2015 -0700 Committer: Tony Sun <tony....@cloudant.com> Committed: Tue Aug 25 13:23:53 2015 -0700 ---------------------------------------------------------------------- src/mango_selector.erl | 15 +++++++++++++++ src/mango_selector_text.erl | 8 +++++++- test/06-basic-text-test.py | 18 ++++++++++++++++++ test/friend_docs.py | 4 +++- 4 files changed, 43 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/10fcac2b/src/mango_selector.erl ---------------------------------------------------------------------- diff --git a/src/mango_selector.erl b/src/mango_selector.erl index c008a4c..21c55ae 100644 --- a/src/mango_selector.erl +++ b/src/mango_selector.erl @@ -411,6 +411,21 @@ match({[{<<"$all">>, Args}]}, Values, _Cmp) when is_list(Values) -> match({[{<<"$all">>, _Args}]}, _Values, _Cmp) -> false; +%% This is for $elemMatch and possibly $in because of our normalizer. +%% A selector such as {"field_name": {"$elemMatch": {"$gte": 80, "$lt": 85}}} +%% gets normalized to: +%% {[{<<"field_name">>, +%% {[{<<"$elemMatch">>, +%% {[{<<"$and">>, [ +%% {[{<<>>,{[{<<"$gte">>,80}]}}]}, +%% {[{<<>>,{[{<<"$lt">>,85}]}}]} +%% ]}]} +%% }]} +%% }]}. +%% So we filter out the <<>>. +match({[{<<>>, Arg}]}, Values, Cmp) -> + match(Arg, Values, Cmp); + % Matches when any element in values matches the % sub-selector Arg. match({[{<<"$elemMatch">>, Arg}]}, Values, Cmp) when is_list(Values) -> http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/10fcac2b/src/mango_selector_text.erl ---------------------------------------------------------------------- diff --git a/src/mango_selector_text.erl b/src/mango_selector_text.erl index 74a4012..24d4ad1 100644 --- a/src/mango_selector_text.erl +++ b/src/mango_selector_text.erl @@ -274,7 +274,13 @@ path_str([Part], Acc) -> % during recursion of convert. [Part | Acc]; path_str([Part | Rest], Acc) -> - path_str(Rest, [<<".">>, Part | Acc]). + case Part of + % do not append a period if Part is blank + <<>> -> + path_str(Rest, [Acc]); + _ -> + path_str(Rest, [<<".">>, Part | Acc]) + end. type_str(Value) when is_number(Value) -> http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/10fcac2b/test/06-basic-text-test.py ---------------------------------------------------------------------- diff --git a/test/06-basic-text-test.py b/test/06-basic-text-test.py index baf912b..670fad5 100644 --- a/test/06-basic-text-test.py +++ b/test/06-basic-text-test.py @@ -404,6 +404,24 @@ class ElemMatchTests(mango.FriendDocsTextTests): def setUpClass(klass): raise unittest.SkipTest('text index is not supported yet') + def test_elem_match_non_object(self): + q = {"bestfriends":{ + "$elemMatch": + {"$eq":"Wolverine", "$eq":"Cyclops"} + } + } + docs = self.db.find(q) + print len(docs) + assert len(docs) == 1 + assert docs[0]["bestfriends"] == ["Wolverine", "Cyclops"] + + q = {"results": {"$elemMatch": {"$gte": 80, "$lt": 85}}} + + docs = self.db.find(q) + print len(docs) + assert len(docs) == 1 + assert docs[0]["results"] == [82, 85, 88] + def test_elem_match(self): q = {"friends": { "$elemMatch": http://git-wip-us.apache.org/repos/asf/couchdb-mango/blob/10fcac2b/test/friend_docs.py ---------------------------------------------------------------------- diff --git a/test/friend_docs.py b/test/friend_docs.py index 8bba58d..ec2c082 100644 --- a/test/friend_docs.py +++ b/test/friend_docs.py @@ -461,7 +461,8 @@ DOCS = [ }, "type": "personal" } - ] + ], + "bestfriends" : ["Wolverine", "Cyclops"] }, { "_id": "54a431719faa420a5b4fbeb0", @@ -530,6 +531,7 @@ DOCS = [ "type": "work" } ] + "results": [ 82, 85, 88 ] }, { "_id": "54a4317132f2c81561833259",