Skip to content
Original file line number Diff line number Diff line change
Expand Up @@ -21,32 +21,31 @@
import com.google.firebase.firestore.util.Preconditions;

/**
* A {@code AggregateQuery} computes some aggregation statistics from the result set of a base
* {@link Query}.
* A query that calculates aggregations over an underlying query.
*
* <p><b>Subclassing Note</b>: Cloud Firestore classes are not meant to be subclassed except for use
* in test mocks. Subclassing is not supported in production code and new SDK releases may break
* code that does so.
*/
public class AggregateQuery {
// The base query.

private final Query query;

AggregateQuery(@NonNull Query query) {
this.query = query;
}

/** Returns the base {@link Query} for this aggregate query. */
/** Returns the query whose aggregations will be calculated by this object. */
@NonNull
public Query getQuery() {
return query;
}

/**
* Executes the aggregate query and returns the results as a {@code AggregateQuerySnapshot}.
* Executes this query.
*
* @param source A value to configure the get behavior.
* @return A Task that will be resolved with the results of the {@code AggregateQuery}.
* @param source The source from which to acquire the aggregate results.
* @return A {@link Task} that will be resolved with the results of the query.
*/
@NonNull
public Task<AggregateQuerySnapshot> get(@NonNull AggregateSource source) {
Expand All @@ -70,14 +69,35 @@ public Task<AggregateQuerySnapshot> get(@NonNull AggregateSource source) {
return tcs.getTask();
}

/**
* Compares this object with the given object for equality.
*
* <p>This object is considered "equal" to the other object if and only if all of the following

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please double-check whether closing

and tags are required here and a few lines below, and in corresponding docstrings in other source files.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I originally had the closings tags in there, but the code formatter actually removed them!

* conditions are satisfied:
*
* <ol>
* <li>{@code object} is a non-null instance of {@link AggregateQuery}.
* <li>{@code object} performs the same aggregations as this {@link AggregateQuery}.
* <li>The underlying {@link Query} of {@code object} compares equal to that of this object.
* </ol>
*
* @param object The object to compare to this object for equality.
* @return {@code true} if this object is "equal" to the given object, as defined above, or {@code
* false} otherwise.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AggregateQuery)) return false;
AggregateQuery that = (AggregateQuery) o;
return query.equals(that.query);
public boolean equals(Object object) {
if (this == object) return true;
if (!(object instanceof AggregateQuery)) return false;
AggregateQuery other = (AggregateQuery) object;
return query.equals(other.query);
}

/**
* Calculates and returns the hash code for this object.
*
* @return the hash code for this object.
*/
@Override
public int hashCode() {
return query.hashCode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@
import java.util.Objects;

/**
* A {@code AggregateQuerySnapshot} contains results of a {@link AggregateQuery}.
* The results of executing an {@link AggregateQuery}.
*
* <p><b>Subclassing Note</b>: Cloud Firestore classes are not meant to be subclassed except for use
* in test mocks. Subclassing is not supported in production code and new SDK releases may break
Expand All @@ -37,25 +37,46 @@ public class AggregateQuerySnapshot {
this.count = count;
}

/** @return The original {@link AggregateQuery} this snapshot is a result of. */
/** Returns the query that was executed to produce this result. */
@NonNull
public AggregateQuery getQuery() {
return query;
}

/** @return The result of a document count aggregation. */
/** Returns the number of documents in the result set of the underlying query. */
public long getCount() {
return count;
}

/**
* Compares this object with the given object for equality.
*
* <p>This object is considered "equal" to the other object if and only if all of the following
* conditions are satisfied:
*
* <ol>
* <li>{@code object} is a non-null instance of {@link AggregateQuerySnapshot}.
* <li>The {@link AggregateQuery} of {@code object} compares equal to that of this object.
* <li>{@code object} has the same results as this object.
* </ol>
*
* @param object The object to compare to this object for equality.
* @return {@code true} if this object is "equal" to the given object, as defined above, or {@code
* false} otherwise.
*/
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof AggregateQuerySnapshot)) return false;
AggregateQuerySnapshot snapshot = (AggregateQuerySnapshot) o;
return count == snapshot.count && query.equals(snapshot.query);
public boolean equals(Object object) {
if (this == object) return true;
if (!(object instanceof AggregateQuerySnapshot)) return false;
AggregateQuerySnapshot other = (AggregateQuerySnapshot) object;
return count == other.count && query.equals(other.query);
}

/**
* Calculates and returns the hash code for this object.
*
* @return the hash code for this object.
*/
@Override
public int hashCode() {
return Objects.hash(count, query);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,23 @@

package com.google.firebase.firestore;

/** Configures the behavior of {@link AggregateQuery#get}. */
/**
* The sources from which an {@link AggregateQuery} can retrieve its results.
*
* @see AggregateQuery#get
*/
public enum AggregateSource {
/**
* Reach to the Firestore backend and surface the result verbatim, that is no local documents or
* mutations in the SDK cache will be included in the surfaced result.
* Perform the aggregation on the server and download the result.
*
* <p>Requires client to be online.
* <p>The result received from the server is presented, unaltered, without considering any local
* state. That is, documents in the local cache are not taken into consideration, neither are
* local modifications not yet synchronized with the server. Previously-downloaded results, if
* any, are not used: every request using this source necessarily involves a round trip to the
* server.
*
* <p>The {@link AggregateQuery} will fail if the server cannot be reached, such as if the client
* is offline.
*/
SERVER,
}
Original file line number Diff line number Diff line change
Expand Up @@ -1224,10 +1224,16 @@ private void validateHasExplicitOrderByForLimitToLast() {
}

/**
* Creates an {@link AggregateQuery} counting the number of documents matching this query.
* Returns a query that counts the documents in the result set of this query.
*
* @return An {@link AggregateQuery} object that can be used to count the number of documents in
* the result set of this query.
* <p>The returned query, when executed, counts the documents in the result set of this query
* <em>without actually downloading the documents</em>.
*
* <p>Using the returned query to count the documents is efficient because only the final count,
* not the documents' data, is downloaded. The returned query can even count the documents if the
* result set would be prohibitively large to download entirely (e.g. thousands of documents).
*
* @return a query that counts the documents in the result set of this query.
*/
@NonNull
public AggregateQuery count() {
Expand Down