@@ -1020,3 +1020,115 @@ def _collection_group_query_response_to_snapshot(
10201020 update_time = response_pb ._pb .document .update_time ,
10211021 )
10221022 return snapshot
1023+
1024+
1025+ class BaseCollectionGroup (BaseQuery ):
1026+ """Represents a Collection Group in the Firestore API.
1027+
1028+ This is a specialization of :class:`.Query` that includes all documents in the
1029+ database that are contained in a collection or subcollection of the given
1030+ parent.
1031+
1032+ Args:
1033+ parent (:class:`~google.cloud.firestore_v1.collection.CollectionReference`):
1034+ The collection that this query applies to.
1035+ """
1036+
1037+ _PARTITION_QUERY_ORDER = (
1038+ BaseQuery ._make_order (
1039+ field_path_module .FieldPath .document_id (), BaseQuery .ASCENDING ,
1040+ ),
1041+ )
1042+
1043+ def __init__ (
1044+ self ,
1045+ parent ,
1046+ projection = None ,
1047+ field_filters = (),
1048+ orders = (),
1049+ limit = None ,
1050+ limit_to_last = False ,
1051+ offset = None ,
1052+ start_at = None ,
1053+ end_at = None ,
1054+ all_descendants = True ,
1055+ ) -> None :
1056+ if not all_descendants :
1057+ raise ValueError ("all_descendants must be True for collection group query." )
1058+
1059+ super (BaseCollectionGroup , self ).__init__ (
1060+ parent = parent ,
1061+ projection = projection ,
1062+ field_filters = field_filters ,
1063+ orders = orders ,
1064+ limit = limit ,
1065+ limit_to_last = limit_to_last ,
1066+ offset = offset ,
1067+ start_at = start_at ,
1068+ end_at = end_at ,
1069+ all_descendants = all_descendants ,
1070+ )
1071+
1072+ def _validate_partition_query (self ):
1073+ if self ._field_filters :
1074+ raise ValueError ("Can't partition query with filters." )
1075+
1076+ if self ._projection :
1077+ raise ValueError ("Can't partition query with projection." )
1078+
1079+ if self ._limit :
1080+ raise ValueError ("Can't partition query with limit." )
1081+
1082+ if self ._offset :
1083+ raise ValueError ("Can't partition query with offset." )
1084+
1085+
1086+ class QueryPartition :
1087+ """Represents a bounded partition of a collection group query.
1088+
1089+ Contains cursors that can be used in a query as a starting and/or end point for the
1090+ collection group query. The cursors may only be used in a query that matches the
1091+ constraints of the query that produced this partition.
1092+
1093+ Args:
1094+ query (BaseQuery): The original query that this is a partition of.
1095+ start_at (Optional[~google.cloud.firestore_v1.document.DocumentSnapshot]):
1096+ Cursor for first query result to include. If `None`, the partition starts at
1097+ the beginning of the result set.
1098+ end_at (Optional[~google.cloud.firestore_v1.document.DocumentSnapshot]):
1099+ Cursor for first query result after the last result included in the
1100+ partition. If `None`, the partition runs to the end of the result set.
1101+
1102+ """
1103+
1104+ def __init__ (self , query , start_at , end_at ):
1105+ self ._query = query
1106+ self ._start_at = start_at
1107+ self ._end_at = end_at
1108+
1109+ @property
1110+ def start_at (self ):
1111+ return self ._start_at
1112+
1113+ @property
1114+ def end_at (self ):
1115+ return self ._end_at
1116+
1117+ def query (self ):
1118+ """Generate a new query using this partition's bounds.
1119+
1120+ Returns:
1121+ BaseQuery: Copy of the original query with start and end bounds set by the
1122+ cursors from this partition.
1123+ """
1124+ query = self ._query
1125+ start_at = ([self .start_at ], True ) if self .start_at else None
1126+ end_at = ([self .end_at ], True ) if self .end_at else None
1127+
1128+ return type (query )(
1129+ query ._parent ,
1130+ all_descendants = query ._all_descendants ,
1131+ orders = query ._PARTITION_QUERY_ORDER ,
1132+ start_at = start_at ,
1133+ end_at = end_at ,
1134+ )
0 commit comments