@@ -60,6 +60,9 @@ def __init__(self, kind=None, dataset=None, namespace=None):
6060 self ._namespace = namespace
6161 self ._pb = datastore_pb .Query ()
6262 self ._cursor = None
63+ self ._projection = []
64+ self ._offset = 0
65+ self ._group_by = []
6366
6467 if kind :
6568 self ._pb .kind .add ().name = kind
@@ -404,3 +407,104 @@ def order(self, *properties):
404407 property_order .direction = property_order .ASCENDING
405408
406409 return clone
410+
411+ def projection (self , projection = None ):
412+ """Adds a projection to the query.
413+
414+ This is a hybrid getter / setter, used as::
415+
416+ >>> query = Query('Person')
417+ >>> query.projection() # Get the projection for this query.
418+ []
419+ >>> query = query.projection(['name'])
420+ >>> query.projection() # Get the projection for this query.
421+ ['name']
422+
423+ :type projection: sequence of strings
424+ :param projection: Each value is a string giving the name of a
425+ property to be included in the projection query.
426+
427+ :rtype: :class:`Query` or `list` of strings.
428+ :returns: If no arguments, returns the current projection.
429+ If a projection is provided, returns a clone of the
430+ :class:`Query` with that projection set.
431+ """
432+ if projection is None :
433+ return self ._projection
434+
435+ clone = self ._clone ()
436+ clone ._projection = projection
437+
438+ # Reset projection values to empty.
439+ clone ._pb .projection ._values = []
440+
441+ # Add each name to list of projections.
442+ for projection_name in projection :
443+ clone ._pb .projection .add ().property .name = projection_name
444+ return clone
445+
446+ def offset (self , offset = None ):
447+ """Adds offset to the query to allow pagination.
448+
449+ NOTE: Paging with cursors should be preferred to using an offset.
450+
451+ This is a hybrid getter / setter, used as::
452+
453+ >>> query = Query('Person')
454+ >>> query.offset() # Get the offset for this query.
455+ 0
456+ >>> query = query.offset(10)
457+ >>> query.offset() # Get the offset for this query.
458+ 10
459+
460+ :type offset: non-negative integer.
461+ :param offset: Value representing where to start a query for
462+ a given kind.
463+
464+ :rtype: :class:`Query` or `int`.
465+ :returns: If no arguments, returns the current offset.
466+ If an offset is provided, returns a clone of the
467+ :class:`Query` with that offset set.
468+ """
469+ if offset is None :
470+ return self ._offset
471+
472+ clone = self ._clone ()
473+ clone ._offset = offset
474+ clone ._pb .offset = offset
475+ return clone
476+
477+ def group_by (self , group_by = None ):
478+ """Adds a group_by to the query.
479+
480+ This is a hybrid getter / setter, used as::
481+
482+ >>> query = Query('Person')
483+ >>> query.group_by() # Get the group_by for this query.
484+ []
485+ >>> query = query.group_by(['name'])
486+ >>> query.group_by() # Get the group_by for this query.
487+ ['name']
488+
489+ :type group_by: sequence of strings
490+ :param group_by: Each value is a string giving the name of a
491+ property to use to group results together.
492+
493+ :rtype: :class:`Query` or `list` of strings.
494+ :returns: If no arguments, returns the current group_by.
495+ If a list of group by properties is provided, returns a clone
496+ of the :class:`Query` with that list of values set.
497+ """
498+ if group_by is None :
499+ return self ._group_by
500+
501+ clone = self ._clone ()
502+ clone ._group_by = group_by
503+
504+ # Reset group_by values to empty.
505+ clone ._pb .group_by ._values = []
506+
507+ # Add each name to list of group_bys.
508+ for group_by_name in group_by :
509+ clone ._pb .group_by .add ().name = group_by_name
510+ return clone
0 commit comments