From 475b7188e530a7ae298415e3b0a5844bf713dc97 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 22 Sep 2022 09:49:21 -0400 Subject: [PATCH 1/8] Public Count --- .../google/firebase/firestore/CountTest.java | 48 +++++++------------ .../firebase/firestore/AggregateQuery.java | 2 +- .../firestore/AggregateQuerySnapshot.java | 2 +- .../firebase/firestore/AggregateSource.java | 4 +- .../com/google/firebase/firestore/Query.java | 2 +- 5 files changed, 21 insertions(+), 37 deletions(-) diff --git a/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java b/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java index 5dffb4a70c4..0e7787f2cc2 100644 --- a/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java +++ b/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java @@ -30,19 +30,12 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.firebase.firestore.testutil.IntegrationTestUtil; import org.junit.After; -import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class CountTest { - @Before - public void setUp() { - // TODO(b/243368243): Remove this once backend is ready to support count. - org.junit.Assume.assumeTrue(BuildConfig.USE_EMULATOR_FOR_TESTS); - } - @After public void tearDown() { IntegrationTestUtil.tearDown(); @@ -88,8 +81,7 @@ public void testCanRunCount() { "b", map("k", "b"), "c", map("k", "c"))); - AggregateQuerySnapshot snapshot = - waitFor(collection.count().get(AggregateSource.SERVER_DIRECT)); + AggregateQuerySnapshot snapshot = waitFor(collection.count().get(AggregateSource.SERVER)); assertEquals(Long.valueOf(3), snapshot.getCount()); } @@ -103,7 +95,7 @@ public void testCanRunCountWithFilters() { "c", map("k", "c"))); AggregateQuerySnapshot snapshot = - waitFor(collection.whereEqualTo("k", "b").count().get(AggregateSource.SERVER_DIRECT)); + waitFor(collection.whereEqualTo("k", "b").count().get(AggregateSource.SERVER)); assertEquals(Long.valueOf(1), snapshot.getCount()); } @@ -118,7 +110,7 @@ public void testCanRunCountWithOrderBy() { "d", map("absent", "d"))); AggregateQuerySnapshot snapshot = - waitFor(collection.orderBy("k").count().get(AggregateSource.SERVER_DIRECT)); + waitFor(collection.orderBy("k").count().get(AggregateSource.SERVER)); // "d" is filtered out because it is ordered by "k". assertEquals(Long.valueOf(3), snapshot.getCount()); } @@ -132,7 +124,7 @@ public void testTerminateDoesNotCrashWithFlyingCountQuery() { "b", map("k", "b"), "c", map("k", "c"))); - collection.orderBy("k").count().get(AggregateSource.SERVER_DIRECT); + collection.orderBy("k").count().get(AggregateSource.SERVER); waitFor(collection.firestore.terminate()); } @@ -146,15 +138,15 @@ public void testSnapshotEquals() { "c", map("k", "c"))); AggregateQuerySnapshot snapshot1 = - waitFor(collection.whereEqualTo("k", "b").count().get(AggregateSource.SERVER_DIRECT)); + waitFor(collection.whereEqualTo("k", "b").count().get(AggregateSource.SERVER)); AggregateQuerySnapshot snapshot1_same = - waitFor(collection.whereEqualTo("k", "b").count().get(AggregateSource.SERVER_DIRECT)); + waitFor(collection.whereEqualTo("k", "b").count().get(AggregateSource.SERVER)); AggregateQuerySnapshot snapshot2 = - waitFor(collection.whereEqualTo("k", "a").count().get(AggregateSource.SERVER_DIRECT)); + waitFor(collection.whereEqualTo("k", "a").count().get(AggregateSource.SERVER)); waitFor(collection.document("d").set(map("k", "a"))); AggregateQuerySnapshot snapshot2_different = - waitFor(collection.whereEqualTo("k", "a").count().get(AggregateSource.SERVER_DIRECT)); + waitFor(collection.whereEqualTo("k", "a").count().get(AggregateSource.SERVER)); assertTrue(snapshot1.equals(snapshot1_same)); assertEquals(snapshot1.hashCode(), snapshot1_same.hashCode()); @@ -196,7 +188,7 @@ public void testCanRunCollectionGroupQuery() { waitFor(batch.commit()); AggregateQuerySnapshot snapshot = - waitFor(db.collectionGroup(collectionGroup).count().get(AggregateSource.SERVER_DIRECT)); + waitFor(db.collectionGroup(collectionGroup).count().get(AggregateSource.SERVER)); assertEquals( Long.valueOf(5), // "cg-doc1", "cg-doc2", "cg-doc3", "cg-doc4", "cg-doc5", snapshot.getCount()); @@ -213,17 +205,12 @@ public void testCanRunCountWithFiltersAndLimits() { "d", map("k", "d"))); AggregateQuerySnapshot snapshot = - waitFor( - collection.whereEqualTo("k", "a").limit(2).count().get(AggregateSource.SERVER_DIRECT)); + waitFor(collection.whereEqualTo("k", "a").limit(2).count().get(AggregateSource.SERVER)); assertEquals(Long.valueOf(2), snapshot.getCount()); snapshot = waitFor( - collection - .whereEqualTo("k", "a") - .limitToLast(2) - .count() - .get(AggregateSource.SERVER_DIRECT)); + collection.whereEqualTo("k", "a").limitToLast(2).count().get(AggregateSource.SERVER)); assertEquals(Long.valueOf(2), snapshot.getCount()); snapshot = @@ -232,7 +219,7 @@ public void testCanRunCountWithFiltersAndLimits() { .whereEqualTo("k", "d") .limitToLast(1000) .count() - .get(AggregateSource.SERVER_DIRECT)); + .get(AggregateSource.SERVER)); assertEquals(Long.valueOf(1), snapshot.getCount()); } @@ -240,12 +227,10 @@ public void testCanRunCountWithFiltersAndLimits() { public void testCanRunCountOnNonExistentCollection() { CollectionReference collection = testFirestore().collection("random-coll"); - AggregateQuerySnapshot snapshot = - waitFor(collection.count().get(AggregateSource.SERVER_DIRECT)); + AggregateQuerySnapshot snapshot = waitFor(collection.count().get(AggregateSource.SERVER)); assertEquals(Long.valueOf(0), snapshot.getCount()); - snapshot = - waitFor(collection.whereEqualTo("k", 100).count().get(AggregateSource.SERVER_DIRECT)); + snapshot = waitFor(collection.whereEqualTo("k", 100).count().get(AggregateSource.SERVER)); assertEquals(Long.valueOf(0), snapshot.getCount()); } @@ -259,14 +244,13 @@ public void testFailWithoutNetwork() { "c", map("k", "c"))); waitFor(collection.getFirestore().disableNetwork()); - Exception e = waitForException(collection.count().get(AggregateSource.SERVER_DIRECT)); + Exception e = waitForException(collection.count().get(AggregateSource.SERVER)); assertThat(e, instanceOf(FirebaseFirestoreException.class)); assertEquals( FirebaseFirestoreException.Code.UNAVAILABLE, ((FirebaseFirestoreException) e).getCode()); waitFor(collection.getFirestore().enableNetwork()); - AggregateQuerySnapshot snapshot = - waitFor(collection.count().get(AggregateSource.SERVER_DIRECT)); + AggregateQuerySnapshot snapshot = waitFor(collection.count().get(AggregateSource.SERVER)); assertEquals(Long.valueOf(3), snapshot.getCount()); } } diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuery.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuery.java index 179bc6e1b2d..e21eee3f39a 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuery.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuery.java @@ -28,7 +28,7 @@ * in test mocks. Subclassing is not supported in production code and new SDK releases may break * code that does so. */ -class AggregateQuery { +public class AggregateQuery { // The base query. private final Query query; diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java index 0ec69134471..74b04383fd4 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java @@ -27,7 +27,7 @@ * in test mocks. Subclassing is not supported in production code and new SDK releases may break * code that does so. */ -class AggregateQuerySnapshot { +public class AggregateQuerySnapshot { private final long count; private final AggregateQuery query; diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateSource.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateSource.java index afb235df184..abb67c58518 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateSource.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateSource.java @@ -15,12 +15,12 @@ package com.google.firebase.firestore; /** Configures the behavior of {@link AggregateQuery#get}. */ -enum AggregateSource { +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. * *

Requires client to be online. */ - SERVER_DIRECT, + SERVER, } diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/Query.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/Query.java index 125b93c53a4..278c7b96139 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/Query.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/Query.java @@ -1230,7 +1230,7 @@ private void validateHasExplicitOrderByForLimitToLast() { * the result set of this query. */ @NonNull - AggregateQuery count() { + public AggregateQuery count() { return new AggregateQuery(this); } From eb416db607f677b74ea085ab7f1cc974f15deff9 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 22 Sep 2022 10:27:30 -0400 Subject: [PATCH 2/8] Disable prod testing --- .../java/com/google/firebase/firestore/CountTest.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java b/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java index 0e7787f2cc2..1317a413668 100644 --- a/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java +++ b/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java @@ -30,12 +30,19 @@ import androidx.test.ext.junit.runners.AndroidJUnit4; import com.google.firebase.firestore.testutil.IntegrationTestUtil; import org.junit.After; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; @RunWith(AndroidJUnit4.class) public class CountTest { + @Before + public void setUp() { + // TODO(b/243368243): Remove this once backend is ready to support count. + org.junit.Assume.assumeTrue(BuildConfig.USE_EMULATOR_FOR_TESTS); + } + @After public void tearDown() { IntegrationTestUtil.tearDown(); From a1ab574a83e2a064ebc0970e212eb4ae3e49dbe6 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 22 Sep 2022 11:54:35 -0400 Subject: [PATCH 3/8] Long to long --- .../firebase/firestore/AggregateQuerySnapshot.java | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java index 74b04383fd4..6c8cd82d1fc 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java @@ -17,7 +17,6 @@ import static com.google.firebase.firestore.util.Preconditions.checkNotNull; import androidx.annotation.NonNull; -import androidx.annotation.Nullable; import java.util.Objects; /** @@ -44,12 +43,8 @@ public AggregateQuery getQuery() { return query; } - /** - * @return The result of a document count aggregation. Returns null if no count aggregation is - * available in the result. - */ - @Nullable - public Long getCount() { + /** @return The result of a document count aggregation. */ + public long getCount() { return count; } From 77a4598c1246bf6e7cc4c0669c8ead769c6bb3d6 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 22 Sep 2022 12:10:16 -0400 Subject: [PATCH 4/8] Api.txt --- firebase-firestore/api.txt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/firebase-firestore/api.txt b/firebase-firestore/api.txt index d7a43041af9..edf6c6ed73b 100644 --- a/firebase-firestore/api.txt +++ b/firebase-firestore/api.txt @@ -19,6 +19,20 @@ package com.google.firebase { package com.google.firebase.firestore { + public class AggregateQuery { + method @NonNull public com.google.android.gms.tasks.Task get(@NonNull com.google.firebase.firestore.AggregateSource); + method @NonNull public com.google.firebase.firestore.Query getQuery(); + } + + public class AggregateQuerySnapshot { + method public long getCount(); + method @NonNull public com.google.firebase.firestore.AggregateQuery getQuery(); + } + + public enum AggregateSource { + enum_constant public static final com.google.firebase.firestore.AggregateSource SERVER; + } + public class Blob implements java.lang.Comparable { method public int compareTo(@NonNull com.google.firebase.firestore.Blob); method @NonNull public static com.google.firebase.firestore.Blob fromBytes(@NonNull byte[]); @@ -290,6 +304,7 @@ package com.google.firebase.firestore { method @NonNull public com.google.firebase.firestore.ListenerRegistration addSnapshotListener(@NonNull com.google.firebase.firestore.MetadataChanges, @NonNull com.google.firebase.firestore.EventListener); method @NonNull public com.google.firebase.firestore.ListenerRegistration addSnapshotListener(@NonNull java.util.concurrent.Executor, @NonNull com.google.firebase.firestore.MetadataChanges, @NonNull com.google.firebase.firestore.EventListener); method @NonNull public com.google.firebase.firestore.ListenerRegistration addSnapshotListener(@NonNull android.app.Activity, @NonNull com.google.firebase.firestore.MetadataChanges, @NonNull com.google.firebase.firestore.EventListener); + method @NonNull public com.google.firebase.firestore.AggregateQuery count(); method @NonNull public com.google.firebase.firestore.Query endAt(@NonNull com.google.firebase.firestore.DocumentSnapshot); method @NonNull public com.google.firebase.firestore.Query endAt(java.lang.Object...); method @NonNull public com.google.firebase.firestore.Query endBefore(@NonNull com.google.firebase.firestore.DocumentSnapshot); From 0ca6582e746e0cfff7e309e867f95e8c4974f3e2 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 22 Sep 2022 13:13:54 -0400 Subject: [PATCH 5/8] Backfill changelog --- firebase-firestore/CHANGELOG.md | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/firebase-firestore/CHANGELOG.md b/firebase-firestore/CHANGELOG.md index fbe940ff32b..c8b29ecc4d4 100644 --- a/firebase-firestore/CHANGELOG.md +++ b/firebase-firestore/CHANGELOG.md @@ -3,8 +3,21 @@ by opting into a release at [go/firebase-android-release](http:go/firebase-android-release) (Googlers only). # Unreleased +- [feature] Added `Query.count()`, which fetches the number of documents in the + result set without actually downloading the documents. + +# 24.3.1 +- [changed] Updated dependency of `io.grpc.*` to its latest version (v1.48.1). + +# 24.3.0 +- [changed] Updated dependency of `play-services-basement` to its latest version (v18.1.0). + +# 24.2.2 - [fixed] Fixed an issue `waitForPendingWrites()` could lead to NullPointerException. +# 24.2.1 +- [changed] Internal refactor and test improvements. + # 24.2.0 - [feature] Added `TransactionOptions` to control how many times a transaction will retry commits before failing. From 9c9c87192120875e3df1221e915e8b7df578a2a4 Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Thu, 22 Sep 2022 13:28:24 -0400 Subject: [PATCH 6/8] Add PR --- firebase-firestore/CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/firebase-firestore/CHANGELOG.md b/firebase-firestore/CHANGELOG.md index c8b29ecc4d4..9dfb14ef0da 100644 --- a/firebase-firestore/CHANGELOG.md +++ b/firebase-firestore/CHANGELOG.md @@ -4,7 +4,7 @@ by opting into a release at # Unreleased - [feature] Added `Query.count()`, which fetches the number of documents in the - result set without actually downloading the documents. + result set without actually downloading the documents (#4130). # 24.3.1 - [changed] Updated dependency of `io.grpc.*` to its latest version (v1.48.1). From 6a0c6108f9d0921d04a5df702813827fb640dbad Mon Sep 17 00:00:00 2001 From: Wu-Hui Date: Fri, 23 Sep 2022 11:05:12 -0400 Subject: [PATCH 7/8] Fix assertEquals error --- .../google/firebase/firestore/CountTest.java | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java b/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java index 1317a413668..155de0dc63a 100644 --- a/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java +++ b/firebase-firestore/src/androidTest/java/com/google/firebase/firestore/CountTest.java @@ -89,7 +89,7 @@ public void testCanRunCount() { "c", map("k", "c"))); AggregateQuerySnapshot snapshot = waitFor(collection.count().get(AggregateSource.SERVER)); - assertEquals(Long.valueOf(3), snapshot.getCount()); + assertEquals(3L, snapshot.getCount()); } @Test @@ -103,7 +103,7 @@ public void testCanRunCountWithFilters() { AggregateQuerySnapshot snapshot = waitFor(collection.whereEqualTo("k", "b").count().get(AggregateSource.SERVER)); - assertEquals(Long.valueOf(1), snapshot.getCount()); + assertEquals(1L, snapshot.getCount()); } @Test @@ -119,7 +119,7 @@ public void testCanRunCountWithOrderBy() { AggregateQuerySnapshot snapshot = waitFor(collection.orderBy("k").count().get(AggregateSource.SERVER)); // "d" is filtered out because it is ordered by "k". - assertEquals(Long.valueOf(3), snapshot.getCount()); + assertEquals(3L, snapshot.getCount()); } @Test @@ -197,7 +197,7 @@ public void testCanRunCollectionGroupQuery() { AggregateQuerySnapshot snapshot = waitFor(db.collectionGroup(collectionGroup).count().get(AggregateSource.SERVER)); assertEquals( - Long.valueOf(5), // "cg-doc1", "cg-doc2", "cg-doc3", "cg-doc4", "cg-doc5", + 5L, // "cg-doc1", "cg-doc2", "cg-doc3", "cg-doc4", "cg-doc5", snapshot.getCount()); } @@ -213,12 +213,12 @@ public void testCanRunCountWithFiltersAndLimits() { AggregateQuerySnapshot snapshot = waitFor(collection.whereEqualTo("k", "a").limit(2).count().get(AggregateSource.SERVER)); - assertEquals(Long.valueOf(2), snapshot.getCount()); + assertEquals(2L, snapshot.getCount()); snapshot = waitFor( collection.whereEqualTo("k", "a").limitToLast(2).count().get(AggregateSource.SERVER)); - assertEquals(Long.valueOf(2), snapshot.getCount()); + assertEquals(2L, snapshot.getCount()); snapshot = waitFor( @@ -227,7 +227,7 @@ public void testCanRunCountWithFiltersAndLimits() { .limitToLast(1000) .count() .get(AggregateSource.SERVER)); - assertEquals(Long.valueOf(1), snapshot.getCount()); + assertEquals(1L, snapshot.getCount()); } @Test @@ -235,10 +235,10 @@ public void testCanRunCountOnNonExistentCollection() { CollectionReference collection = testFirestore().collection("random-coll"); AggregateQuerySnapshot snapshot = waitFor(collection.count().get(AggregateSource.SERVER)); - assertEquals(Long.valueOf(0), snapshot.getCount()); + assertEquals(0L, snapshot.getCount()); snapshot = waitFor(collection.whereEqualTo("k", 100).count().get(AggregateSource.SERVER)); - assertEquals(Long.valueOf(0), snapshot.getCount()); + assertEquals(0L, snapshot.getCount()); } @Test @@ -258,6 +258,6 @@ public void testFailWithoutNetwork() { waitFor(collection.getFirestore().enableNetwork()); AggregateQuerySnapshot snapshot = waitFor(collection.count().get(AggregateSource.SERVER)); - assertEquals(Long.valueOf(3), snapshot.getCount()); + assertEquals(3L, snapshot.getCount()); } } From 45e10309f4dcbe09f777b43be70d4eecb9b2a9e1 Mon Sep 17 00:00:00 2001 From: Denver Coneybeare Date: Mon, 26 Sep 2022 17:23:03 -0400 Subject: [PATCH 8/8] Re-write API javadocs for COUNT API (#4143) --- .../firebase/firestore/AggregateQuery.java | 44 ++++++++++++++----- .../firestore/AggregateQuerySnapshot.java | 37 ++++++++++++---- .../firebase/firestore/AggregateSource.java | 18 ++++++-- .../com/google/firebase/firestore/Query.java | 12 +++-- 4 files changed, 84 insertions(+), 27 deletions(-) diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuery.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuery.java index e21eee3f39a..cb7f1684759 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuery.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuery.java @@ -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. * *

Subclassing Note: 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 get(@NonNull AggregateSource source) { @@ -70,14 +69,35 @@ public Task get(@NonNull AggregateSource source) { return tcs.getTask(); } + /** + * Compares this object with the given object for equality. + * + *

This object is considered "equal" to the other object if and only if all of the following + * conditions are satisfied: + * + *

    + *
  1. {@code object} is a non-null instance of {@link AggregateQuery}. + *
  2. {@code object} performs the same aggregations as this {@link AggregateQuery}. + *
  3. The underlying {@link Query} of {@code object} compares equal to that of this object. + *
+ * + * @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(); diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java index 6c8cd82d1fc..2d8ee7be8f0 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateQuerySnapshot.java @@ -20,7 +20,7 @@ import java.util.Objects; /** - * A {@code AggregateQuerySnapshot} contains results of a {@link AggregateQuery}. + * The results of executing an {@link AggregateQuery}. * *

Subclassing Note: 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 @@ -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. + * + *

This object is considered "equal" to the other object if and only if all of the following + * conditions are satisfied: + * + *

    + *
  1. {@code object} is a non-null instance of {@link AggregateQuerySnapshot}. + *
  2. The {@link AggregateQuery} of {@code object} compares equal to that of this object. + *
  3. {@code object} has the same results as this object. + *
+ * + * @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); diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateSource.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateSource.java index abb67c58518..31402ba99e4 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateSource.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/AggregateSource.java @@ -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. * - *

Requires client to be online. + *

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. + * + *

The {@link AggregateQuery} will fail if the server cannot be reached, such as if the client + * is offline. */ SERVER, } diff --git a/firebase-firestore/src/main/java/com/google/firebase/firestore/Query.java b/firebase-firestore/src/main/java/com/google/firebase/firestore/Query.java index 278c7b96139..8db1e9ff8db 100644 --- a/firebase-firestore/src/main/java/com/google/firebase/firestore/Query.java +++ b/firebase-firestore/src/main/java/com/google/firebase/firestore/Query.java @@ -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. + *

The returned query, when executed, counts the documents in the result set of this query + * without actually downloading the documents. + * + *

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() {