Compilation of combinations - simple $or now works
This commit is contained in:
parent
62388cb740
commit
a3c46fec07
@ -43,6 +43,20 @@ class QNodeVisitor(object):
|
|||||||
def visit_query(self, query):
|
def visit_query(self, query):
|
||||||
return query
|
return query
|
||||||
|
|
||||||
|
def _query_conjunction(self, queries):
|
||||||
|
query_ops = set()
|
||||||
|
combined_query = {}
|
||||||
|
for query in queries:
|
||||||
|
ops = set(query.keys())
|
||||||
|
intersection = ops.intersection(query_ops)
|
||||||
|
if intersection:
|
||||||
|
msg = 'Duplicate query contitions: '
|
||||||
|
raise InvalidQueryError(msg + ', '.join(intersection))
|
||||||
|
|
||||||
|
query_ops.update(ops)
|
||||||
|
combined_query.update(copy.deepcopy(query))
|
||||||
|
return combined_query
|
||||||
|
|
||||||
|
|
||||||
class SimplificationVisitor(QNodeVisitor):
|
class SimplificationVisitor(QNodeVisitor):
|
||||||
|
|
||||||
@ -53,18 +67,8 @@ class SimplificationVisitor(QNodeVisitor):
|
|||||||
if any(not isinstance(node, NewQ) for node in combination.children):
|
if any(not isinstance(node, NewQ) for node in combination.children):
|
||||||
return combination
|
return combination
|
||||||
|
|
||||||
query_ops = set()
|
queries = [node.query for node in combination.children]
|
||||||
query = {}
|
return NewQ(**self._query_conjunction(queries))
|
||||||
for node in combination.children:
|
|
||||||
ops = set(node.query.keys())
|
|
||||||
intersection = ops.intersection(query_ops)
|
|
||||||
if intersection:
|
|
||||||
msg = 'Duplicate query contitions: '
|
|
||||||
raise InvalidQueryError(msg + ', '.join(intersection))
|
|
||||||
|
|
||||||
query_ops.update(ops)
|
|
||||||
query.update(copy.deepcopy(node.query))
|
|
||||||
return NewQ(**query)
|
|
||||||
|
|
||||||
|
|
||||||
class QueryCompilerVisitor(QNodeVisitor):
|
class QueryCompilerVisitor(QNodeVisitor):
|
||||||
@ -74,7 +78,9 @@ class QueryCompilerVisitor(QNodeVisitor):
|
|||||||
|
|
||||||
def visit_combination(self, combination):
|
def visit_combination(self, combination):
|
||||||
if combination.operation == combination.OR:
|
if combination.operation == combination.OR:
|
||||||
return combination
|
return {'$or': combination.children}
|
||||||
|
elif combination.operation == combination.AND:
|
||||||
|
return self._query_conjunction(combination.children)
|
||||||
return combination
|
return combination
|
||||||
|
|
||||||
def visit_query(self, query):
|
def visit_query(self, query):
|
||||||
|
@ -1432,5 +1432,19 @@ class NewQTest(unittest.TestCase):
|
|||||||
query = (q1 & q2).to_query(TestDoc)
|
query = (q1 & q2).to_query(TestDoc)
|
||||||
self.assertEqual(query, {'x': {'$lt': 7, '$gt': 3}})
|
self.assertEqual(query, {'x': {'$lt': 7, '$gt': 3}})
|
||||||
|
|
||||||
|
def test_or_combination(self):
|
||||||
|
class TestDoc(Document):
|
||||||
|
x = IntField()
|
||||||
|
|
||||||
|
q1 = NewQ(x__lt=3)
|
||||||
|
q2 = NewQ(x__gt=7)
|
||||||
|
query = (q1 | q2).to_query(TestDoc)
|
||||||
|
self.assertEqual(query, {
|
||||||
|
'$or': [
|
||||||
|
{'x': {'$lt': 3}},
|
||||||
|
{'x': {'$gt': 7}},
|
||||||
|
]
|
||||||
|
})
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
unittest.main()
|
unittest.main()
|
||||||
|
Loading…
x
Reference in New Issue
Block a user