Esempio n. 1
0
  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
Esempio n. 2
0
  def filter(self, expression, value):
    """Filter the query based on an expression and a value.

    This will return a clone of the current :class:`Query`
    filtered by the expression and value provided.

    Expressions take the form of::

      .filter('<property> <operator>', <value>)

    where property is a property stored on the entity in the datastore
    and operator is one of ``OPERATORS``
    (ie, ``=``, ``<``, ``<=``, ``>``, ``>=``)::

      >>> query = Query('Person')
      >>> filtered_query = query.filter('name =', 'James')
      >>> filtered_query = query.filter('age >', 50)

    Because each call to ``.filter()`` returns a cloned ``Query`` object
    we are able to string these together::

      >>> query = Query('Person').filter('name =', 'James').filter('age >', 50)

    :type expression: string
    :param expression: An expression of a property and an operator (ie, ``=``).

    :type value: integer, string, boolean, float, None, datetime
    :param value: The value to filter on.

    :rtype: :class:`Query`
    :returns: A Query filtered by the expression and value provided.
    """
    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
Esempio n. 3
0
  def save_entity(self, dataset_id, key_pb, properties):
    """Save an entity to the Cloud Datastore with the provided properties.

    :type dataset_id: string
    :param dataset_id: The dataset in which to save the entity.

    :type key_pb: :class:`gclouddatastore.datastore_v1_pb2.Key`
    :param key_pb: The complete or partial key for the entity.

    :type properties: dict
    :param properties: The properties to store on the entity.
    """
    # TODO: Is this the right method name?
    # TODO: How do you delete properties? Set them to None?
    mutation = self.mutation()

    # If the Key is complete, we should upsert
    # instead of using insert_auto_id.
    path = key_pb.path_element[-1]
    auto_id = not (path.HasField('id') or path.HasField('name'))

    if auto_id:
      insert = mutation.insert_auto_id.add()
    else:
      insert = mutation.upsert.add()

    insert.key.CopyFrom(key_pb)

    for name, value in properties.iteritems():
      prop = insert.property.add()
      # Set the name of the property.
      prop.name = name

      # Set the appropriate value.
      pb_attr, pb_value = helpers.get_protobuf_attribute_and_value(value)
      setattr(prop.value, pb_attr, pb_value)

    # If this is in a transaction, we should just return True. The transaction
    # will handle assigning any keys as necessary.
    if self.transaction():
      return True

    result = self.commit(dataset_id, mutation)
    # If this was an auto-assigned ID, return the new Key.
    if auto_id:
      return result.insert_auto_id_key[0]

    return True
Esempio n. 4
0
  def save_entity(self, entity):
    # Create a non-transactional commit request.
    commit_request = datastore_pb.CommitRequest()
    commit_request.mode = datastore_pb.CommitRequest.NON_TRANSACTIONAL

    mutation = commit_request.mutation.insert_auto_id.add()

    # First set the (partial) key.
    mutation.key.CopyFrom(entity.key().to_protobuf())

    for name, value in entity.iteritems():
      prop = mutation.property.add()
      # Set the name of the property.
      prop.name = name

      # Set the appropriate value.
      pb_attr, pb_value = helpers.get_protobuf_attribute_and_value(value)
      setattr(prop.value, pb_attr, pb_value)

    response = self._rpc('commit', commit_request, datastore_pb.CommitResponse)

    return response.mutation_result.insert_auto_id_key[0]