From 196606438ccd05589ec25221ddf60346285e9101 Mon Sep 17 00:00:00 2001 From: Harry Marr Date: Sun, 30 May 2010 18:34:06 +0100 Subject: [PATCH] Fixed Q-object list query issue --- mongoengine/queryset.py | 9 +++++++-- tests/queryset.py | 25 +++++++++++++++++++++++-- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/mongoengine/queryset.py b/mongoengine/queryset.py index 57600b10..069ab113 100644 --- a/mongoengine/queryset.py +++ b/mongoengine/queryset.py @@ -36,7 +36,9 @@ class Q(object): OR = '||' AND = '&&' OPERATORS = { - 'eq': 'this.%(field)s == %(value)s', + 'eq': ('((this.%(field)s instanceof Array) && ' + ' this.%(field)s.indexOf(%(value)s) != -1) ||' + ' this.%(field)s == %(value)s'), 'ne': 'this.%(field)s != %(value)s', 'gt': 'this.%(field)s > %(value)s', 'gte': 'this.%(field)s >= %(value)s', @@ -62,7 +64,8 @@ class Q(object): if not other.query[0]: return self if self.query[0]: - obj.query = ['('] + copy.deepcopy(self.query) + [op] + copy.deepcopy(other.query) + [')'] + obj.query = (['('] + copy.deepcopy(self.query) + [op] + + copy.deepcopy(other.query) + [')']) else: obj.query = copy.deepcopy(other.query) return obj @@ -111,11 +114,13 @@ class Q(object): value, field_js = self._build_op_js(op, key, value, value_name) js_scope[value_name] = value js.append(field_js) + print ' && '.join(js) return ' && '.join(js) def _build_op_js(self, op, key, value, value_name): """Substitute the values in to the correct chunk of Javascript. """ + print op, key, value, value_name if isinstance(value, RE_TYPE): # Regexes are handled specially if op.strip('$') == 'ne': diff --git a/tests/queryset.py b/tests/queryset.py index e512cd7c..51f92993 100644 --- a/tests/queryset.py +++ b/tests/queryset.py @@ -503,6 +503,22 @@ class QuerySetTest(unittest.TestCase): obj = self.Person.objects(Q(name__ne=re.compile('^Gui'))).first() self.assertEqual(obj, None) + def test_q_lists(self): + """Ensure that Q objects query ListFields correctly. + """ + class BlogPost(Document): + tags = ListField(StringField()) + + BlogPost.drop_collection() + + BlogPost(tags=['python', 'mongo']).save() + BlogPost(tags=['python']).save() + + self.assertEqual(len(BlogPost.objects(Q(tags='mongo'))), 1) + self.assertEqual(len(BlogPost.objects(Q(tags='python'))), 2) + + BlogPost.drop_collection() + def test_exec_js_query(self): """Ensure that queries are properly formed for use in exec_js. """ @@ -1172,10 +1188,15 @@ class QTest(unittest.TestCase): """ q = Q() examples = [ - ({'name': 'test'}, 'this.name == i0f0', {'i0f0': 'test'}), + + ({'name': 'test'}, ('((this.name instanceof Array) && ' + 'this.name.indexOf(i0f0) != -1) || this.name == i0f0'), + {'i0f0': 'test'}), ({'age': {'$gt': 18}}, 'this.age > i0f0o0', {'i0f0o0': 18}), ({'name': 'test', 'age': {'$gt': 18, '$lte': 65}}, - 'this.age <= i0f0o0 && this.age > i0f0o1 && this.name == i0f1', + ('this.age <= i0f0o0 && this.age > i0f0o1 && ' + '((this.name instanceof Array) && ' + 'this.name.indexOf(i0f1) != -1) || this.name == i0f1'), {'i0f0o0': 65, 'i0f0o1': 18, 'i0f1': 'test'}), ] for item, js, scope in examples: