Source code for gclouddatastore.query
import copy
from gclouddatastore import datastore_v1_pb2 as datastore_pb
from gclouddatastore import helpers
# TODO: Figure out how to properly handle namespaces.
[docs]class Query(object):
OPERATORS = {
'<': datastore_pb.PropertyFilter.LESS_THAN,
'<=': datastore_pb.PropertyFilter.LESS_THAN_OR_EQUAL,
'>': datastore_pb.PropertyFilter.GREATER_THAN,
'>=': datastore_pb.PropertyFilter.GREATER_THAN_OR_EQUAL,
'=': datastore_pb.PropertyFilter.EQUAL,
}
def __init__(self, kinds=None, dataset=None):
self._dataset = dataset
self._pb = datastore_pb.Query()
if kinds:
self.kind(*kinds)
def _clone(self):
# TODO(jjg): Double check that this makes sense...
clone = copy.deepcopy(self)
clone._dataset = self._dataset # Shallow copy the dataset.
return clone
[docs] def to_protobuf(self):
return self._pb
[docs] def filter(self, expression, value):
clone = self._clone()
# Take an expression like 'property >=', and parse it into useful pieces.
property_name, operator = None, None
expression = expression.strip()
for operator_string in self.OPERATORS:
if expression.endswith(operator_string):
operator = self.OPERATORS[operator_string]
property_name = expression[0:-len(operator_string)].strip()
if not operator or not property_name:
raise ValueError('Invalid expression: "%s"' % expression)
# Build a composite filter AND'd together.
composite_filter = clone._pb.filter.composite_filter
composite_filter.operator = datastore_pb.CompositeFilter.AND
# Add the specific filter
property_filter = composite_filter.filter.add().property_filter
property_filter.property.name = property_name
property_filter.operator = operator
# Set the value to filter on based on the type.
attr_name, pb_value = helpers.get_protobuf_attribute_and_value(value)
setattr(property_filter.value, attr_name, pb_value)
return clone
[docs] def kind(self, *kinds):
# TODO: Do we want this to be additive?
# If not, clear the _pb.kind attribute.
if kinds:
clone = self._clone()
for kind in kinds:
clone._pb.kind.add().name = kind
return clone
else:
return self._pb.kind
[docs] def limit(self, limit=None):
if limit:
clone = self._clone()
clone._pb.limit = limit
return clone
else:
return self._pb.limit
[docs] def dataset(self, dataset=None):
if dataset:
clone = self._clone()
clone._dataset = dataset
return clone
else:
return self._dataset
[docs] def fetch(self, limit=None):
clone = self
if limit:
clone = self.limit(limit)
return self.dataset().connection().run_query(
query_pb=clone.to_protobuf(), dataset_id=self.dataset().id())