@@ -60,6 +60,9 @@ def __init__(self, kind=None, dataset=None, namespace=None):
60
60
self ._namespace = namespace
61
61
self ._pb = datastore_pb .Query ()
62
62
self ._cursor = None
63
+ self ._projection = []
64
+ self ._offset = 0
65
+ self ._group_by = []
63
66
64
67
if kind :
65
68
self ._pb .kind .add ().name = kind
@@ -404,3 +407,104 @@ def order(self, *properties):
404
407
property_order .direction = property_order .ASCENDING
405
408
406
409
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