Made query-tree code a bit clearer
This commit is contained in:
parent
a3c46fec07
commit
db2f64c290
@ -36,18 +36,28 @@ RE_TYPE = type(re.compile(''))
|
|||||||
|
|
||||||
|
|
||||||
class QNodeVisitor(object):
|
class QNodeVisitor(object):
|
||||||
|
"""Base visitor class for visiting Q-object nodes in a query tree.
|
||||||
|
"""
|
||||||
|
|
||||||
def visit_combination(self, combination):
|
def visit_combination(self, combination):
|
||||||
|
"""Called by QCombination objects.
|
||||||
|
"""
|
||||||
return combination
|
return combination
|
||||||
|
|
||||||
def visit_query(self, query):
|
def visit_query(self, query):
|
||||||
|
"""Called by (New)Q objects.
|
||||||
|
"""
|
||||||
return query
|
return query
|
||||||
|
|
||||||
def _query_conjunction(self, queries):
|
def _query_conjunction(self, queries):
|
||||||
|
"""Merges two query dicts - effectively &ing them together.
|
||||||
|
"""
|
||||||
query_ops = set()
|
query_ops = set()
|
||||||
combined_query = {}
|
combined_query = {}
|
||||||
for query in queries:
|
for query in queries:
|
||||||
ops = set(query.keys())
|
ops = set(query.keys())
|
||||||
|
# Make sure that the same operation isn't applied more than once
|
||||||
|
# to a single field
|
||||||
intersection = ops.intersection(query_ops)
|
intersection = ops.intersection(query_ops)
|
||||||
if intersection:
|
if intersection:
|
||||||
msg = 'Duplicate query contitions: '
|
msg = 'Duplicate query contitions: '
|
||||||
@ -59,11 +69,15 @@ class QNodeVisitor(object):
|
|||||||
|
|
||||||
|
|
||||||
class SimplificationVisitor(QNodeVisitor):
|
class SimplificationVisitor(QNodeVisitor):
|
||||||
|
"""Simplifies query trees by combinging unnecessary 'and' connection nodes
|
||||||
|
into a single Q-object.
|
||||||
|
"""
|
||||||
|
|
||||||
def visit_combination(self, combination):
|
def visit_combination(self, combination):
|
||||||
if combination.operation != combination.AND:
|
if combination.operation != combination.AND:
|
||||||
return combination
|
return combination
|
||||||
|
|
||||||
|
# The simplification only applies to 'simple' queries
|
||||||
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
|
||||||
|
|
||||||
@ -72,6 +86,9 @@ class SimplificationVisitor(QNodeVisitor):
|
|||||||
|
|
||||||
|
|
||||||
class QueryCompilerVisitor(QNodeVisitor):
|
class QueryCompilerVisitor(QNodeVisitor):
|
||||||
|
"""Compiles the nodes in a query tree to a PyMongo-compatible query
|
||||||
|
dictionary.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, document):
|
def __init__(self, document):
|
||||||
self.document = document
|
self.document = document
|
||||||
@ -88,6 +105,8 @@ class QueryCompilerVisitor(QNodeVisitor):
|
|||||||
|
|
||||||
|
|
||||||
class QNode(object):
|
class QNode(object):
|
||||||
|
"""Base class for nodes in query trees.
|
||||||
|
"""
|
||||||
|
|
||||||
AND = 0
|
AND = 0
|
||||||
OR = 1
|
OR = 1
|
||||||
@ -101,6 +120,8 @@ class QNode(object):
|
|||||||
raise NotImplementedError
|
raise NotImplementedError
|
||||||
|
|
||||||
def _combine(self, other, operation):
|
def _combine(self, other, operation):
|
||||||
|
"""Combine this node with another node into a QCombination object.
|
||||||
|
"""
|
||||||
if other.empty:
|
if other.empty:
|
||||||
return self
|
return self
|
||||||
|
|
||||||
@ -121,6 +142,9 @@ class QNode(object):
|
|||||||
|
|
||||||
|
|
||||||
class QCombination(QNode):
|
class QCombination(QNode):
|
||||||
|
"""Represents the combination of several conditions by a given logical
|
||||||
|
operator.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, operation, children):
|
def __init__(self, operation, children):
|
||||||
self.operation = operation
|
self.operation = operation
|
||||||
@ -138,6 +162,9 @@ class QCombination(QNode):
|
|||||||
|
|
||||||
|
|
||||||
class NewQ(QNode):
|
class NewQ(QNode):
|
||||||
|
"""A simple query object, used in a query tree to build up more complex
|
||||||
|
query structures.
|
||||||
|
"""
|
||||||
|
|
||||||
def __init__(self, **query):
|
def __init__(self, **query):
|
||||||
self.query = query
|
self.query = query
|
||||||
|
Loading…
x
Reference in New Issue
Block a user