Eine Aggregationsabfrage verarbeitet die Daten aus mehreren Indexeinträgen, um einen einzelnen Zusammenfassungswert zurückzugeben.
Cloud Firestore unterstützt die folgenden Aggregationsabfragen:
-
count()
-
sum()
-
average()
Cloud Firestore berechnet die Aggregation und überträgt nur das Ergebnis zurück an Ihre App. Im Vergleich zur Ausführung einer vollständigen Abfrage und der Berechnung der Aggregation in Ihrer App sparen Aggregationsabfragen sowohl das Lesen von abgerechneten Dokumenten als auch die übertragenen Bytes ein.
Aggregationsabfragen basieren auf der vorhandenen Indexkonfiguration, die Ihre Abfragen bereits verwenden, und skalieren proportional zur Anzahl der gescannten Indexeinträge. Die Latenz steigt mit der Anzahl der Elemente in der Aggregation.
Verwenden Sie die count()
-Aggregation
Mit der Aggregationsabfrage count()
können Sie die Anzahl der Dokumente in einer Sammlung oder Abfrage ermitteln.
Sehen Sie sich die Beispieldaten an, die wir unter „Daten abrufen“ eingerichtet haben.
Die folgende count()
-Aggregation gibt die Gesamtzahl der Städte in der cities
zurück.
Web modular API
const coll = collection(db, "cities"); const snapshot = await getCountFromServer(coll); console.log('count: ', snapshot.data().count);
Schnell
let query = db.collection("cities") let countQuery = query.count do { let snapshot = try await countQuery.getAggregation(source: .server) print(snapshot.count) } catch { print(error) }
Ziel c
FIRCollectionReference *query = [self.db collectionWithPath:@"cities"]; [query.count aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching count: %@", error); } else { NSLog(@"Cities count: %@", snapshot.count); } }];
Java
Query query = db.collection("cities"); AggregateQuery countQuery = query.count(); countQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Count fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Count: " + snapshot.getCount()); } else { Log.d(TAG, "Count failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities") val countQuery = query.count() countQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Count fetched successfully val snapshot = task.result Log.d(TAG, "Count: ${snapshot.count}") } else { Log.d(TAG, "Count failed: ", task.getException()) } }
Dart
// Returns number of documents in users collection db.collection("users").count().get().then( (res) => print(res.count), onError: (e) => print("Error completing: $e"), );
Gehen
Java
CollectionReference collection = db.collection("cities"); AggregateQuerySnapshot snapshot = collection.count().get().get(); System.out.println("Count: " + snapshot.getCount());
Node.js
const collectionRef = db.collection('cities'); const snapshot = await collectionRef.count().get(); console.log(snapshot.data().count);
Python
Die count()
Aggregation berücksichtigt alle Filter der Abfrage und alle limit
.
Web modular API
const coll = collection(db, "cities"); const q = query(coll, where("state", "==", "CA")); const snapshot = await getCountFromServer(q); console.log('count: ', snapshot.data().count);
Schnell
let query = db.collection("cities").whereField("state", isEqualTo: "CA") let countQuery = query.count do { let snapshot = try await countQuery.getAggregation(source: .server) print(snapshot.count) } catch { print(error) }
Ziel c
FIRQuery *query = [[self.db collectionWithPath:@"cities"] queryWhereField:@"state" isEqualTo:@"CA"]; [query.count aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching count: %@", error); } else { NSLog(@"Cities count: %@", snapshot.count); } }];
Java
Query query = db.collection("cities").whereEqualTo("state", "CA"); AggregateQuery countQuery = query.count(); countQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Count fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Count: " + snapshot.getCount()); } else { Log.d(TAG, "Count failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities").whereEqualTo("state", "CA") val countQuery = query.count() countQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Count fetched successfully val snapshot = task.result Log.d(TAG, "Count: ${snapshot.count}") } else { Log.d(TAG, "Count failed: ", task.getException()) } }
Dart
// This also works with collectionGroup queries. db.collection("users").where("age", isGreaterThan: 10).count().get().then( (res) => print(res.count), onError: (e) => print("Error completing: $e"), );
Gehen
Java
CollectionReference collection = db.collection("cities"); Query query = collection.whereEqualTo("state", "CA"); AggregateQuerySnapshot snapshot = query.count().get().get(); System.out.println("Count: " + snapshot.getCount());
Node.js
const collectionRef = db.collection('cities'); const query = collectionRef.where('state', '==', 'CA'); const snapshot = await query.count().get(); console.log(snapshot.data().count);
Python
Verwenden Sie die sum()
-Aggregation
Verwenden Sie die sum()
-Aggregation, um die Gesamtsumme der numerischen Werte zurückzugeben, die einer bestimmten Abfrage entsprechen – zum Beispiel:
Web modular API
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { totalPopulation: sum('population') }); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Java
collection = db.collection("cities"); snapshot = collection.aggregate(sum("population")).get().get(); System.out.println("Sum: " + snapshot.get(sum("population")));
Node.js
const coll = firestore.collection('cities'); const sumAggregateQuery = coll.aggregate({ totalPopulation: AggregateField.sum('population'), }); const snapshot = await sumAggregateQuery.get(); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Die sum()
Aggregation berücksichtigt alle Filter der Abfrage und alle Limitklauseln – zum Beispiel:
Web modular API
const coll = collection(firestore, 'cities'); const q = query(coll, where('capital', '==', true)); const snapshot = await getAggregateFromServer(q, { totalPopulation: sum('population') }); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Java
collection = db.collection("cities"); query = collection.whereEqualTo("state", "CA"); snapshot = query.aggregate(sum("population")).get().get(); System.out.println("Sum: " + snapshot.get(sum("population")));
Node.js
const coll = firestore.collection('cities'); const q = coll.where("capital", "==", true); const sumAggregateQuery = q.aggregate({ totalPopulation: AggregateField.sum('population'), }); const snapshot = await sumAggregateQuery.get(); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Verwenden Sie die Aggregation average()
Verwenden Sie die Aggregation average()
, um den Durchschnitt numerischer Werte zurückzugeben, die einer bestimmten Abfrage entsprechen – zum Beispiel:
Web modular API
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { averagePopulation: average('population') }); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Java
collection = db.collection("cities"); snapshot = collection.aggregate(average("population")).get().get(); System.out.println("Average: " + snapshot.get(average("population")));
Node.js
const coll = firestore.collection('cities'); const averageAggregateQuery = coll.aggregate({ averagePopulation: AggregateField.average('population'), }); const snapshot = await averageAggregateQuery.get(); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Die Aggregation average()
berücksichtigt alle Filter der Abfrage und alle Limitklauseln – zum Beispiel:
Web modular API
const coll = collection(firestore, 'cities'); const q = query(coll, where('capital', '==', true)); const snapshot = await getAggregateFromServer(q, { averagePopulation: average('population') }); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Java
collection = db.collection("cities"); query = collection.whereEqualTo("state", "CA"); snapshot = query.aggregate(average("population")).get().get(); System.out.println("Average: " + snapshot.get(average("population")));
Node.js
const coll = firestore.collection('cities'); const q = coll.where("capital", "==", true); const averageAggregateQuery = q.aggregate({ averagePopulation: AggregateField.average('population'), }); const snapshot = await averageAggregateQuery.get(); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Berechnen Sie mehrere Aggregationen in einer Abfrage
Sie können mehrere Aggregationen in einer einzigen Aggregationspipeline kombinieren. Dadurch kann die Anzahl der erforderlichen Indexlesevorgänge reduziert werden. Wenn die Abfrage Aggregationen für mehrere Felder umfasst, erfordert die Abfrage möglicherweise einen zusammengesetzten Index. In diesem Fall schlägt Cloud Firestore einen Index vor.
Das folgende Beispiel führt mehrere Aggregationen in einer einzigen Aggregationsabfrage durch:
Web modular API
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { countOfDocs: count(), totalPopulation: sum('population'), averagePopulation: average('population') }); console.log('countOfDocs: ', snapshot.data().countOfDocs); console.log('totalPopulation: ', snapshot.data().totalPopulation); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Java
collection = db.collection("cities"); query = collection.whereEqualTo("state", "CA"); AggregateQuery aggregateQuery = query.aggregate(count(), sum("population"), average("population")); snapshot = aggregateQuery.get().get(); System.out.println("Count: " + snapshot.getCount()); System.out.println("Sum: " + snapshot.get(sum("population"))); System.out.println("Average: " + snapshot.get(average("population")));
Node.js
const coll = firestore.collection('cities'); const aggregateQuery = coll.aggregate({ countOfDocs: AggregateField.count(), totalPopulation: AggregateField.sum('population'), averagePopulation: AggregateField.average('population') }); const snapshot = await aggregateQuery.get(); console.log('countOfDocs: ', snapshot.data().countOfDocs); console.log('totalPopulation: ', snapshot.data().totalPopulation); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Abfragen mit mehreren Aggregationen umfassen nur die Dokumente, die alle Felder in jeder Aggregation enthalten. Dies kann zu unterschiedlichen Ergebnissen führen, wenn jede Aggregation einzeln durchgeführt wird.
Sicherheitsregeln für Aggregationsabfragen
Cloud Firestore-Sicherheitsregeln funktionieren bei Aggregationsabfragen genauso wie bei Abfragen, die Dokumente zurückgeben. Mit anderen Worten: Nur wenn Ihre Regeln es Clients erlauben, bestimmte Sammlungs- oder Sammlungsgruppenabfragen auszuführen, können Clients auch die Aggregation für diese Abfragen durchführen. Erfahren Sie mehr darüber, wie Cloud Firestore-Sicherheitsregeln mit Abfragen interagieren .
Verhalten und Einschränkungen
Beachten Sie beim Arbeiten mit Aggregationsabfragen das folgende Verhalten und die folgenden Einschränkungen:
Sie können Aggregationsabfragen nicht mit Echtzeit-Listenern und Offline-Abfragen verwenden. Aggregationsabfragen werden nur über direkte Serverantwort unterstützt. Abfragen werden nur vom Cloud Firestore-Backend bedient, wobei der lokale Cache und alle gepufferten Aktualisierungen übersprungen werden. Dieses Verhalten ist identisch mit Vorgängen, die innerhalb von Cloud Firestore-Transaktionen ausgeführt werden.
Wenn eine Aggregation nicht innerhalb von 60 Sekunden aufgelöst werden kann, wird der Fehler
DEADLINE_EXCEEDED
zurückgegeben. Die Leistung hängt von Ihrer Indexkonfiguration und der Größe des Datensatzes ab.Wenn der Vorgang nicht innerhalb der Frist von 60 Sekunden abgeschlossen werden kann, besteht eine mögliche Problemumgehung darin, Zähler für große Datensätze zu verwenden.
Aggregationsabfragen lesen aus Indexeinträgen und umfassen nur indizierte Felder.
Durch das Hinzufügen einer
OrderBy
Klausel zu einer Aggregationsabfrage wird die Aggregation auf die Dokumente beschränkt, in denen das Sortierfeld vorhanden ist.Bei
sum()
undaverage()
Aggregationen werden nicht numerische Werte ignoriert. Die Aggregationensum()
undaverage()
berücksichtigen nur ganzzahlige Werte und Gleitkommazahlenwerte.Beachten Sie beim Kombinieren mehrerer Aggregationen in einer einzigen Abfrage, dass
sum()
undaverage()
nicht numerische Werte ignorieren, währendcount()
nicht numerische Werte einschließt.Wenn Sie Aggregationen kombinieren, die sich auf verschiedene Felder beziehen, umfasst die Berechnung nur die Dokumente, die alle diese Felder enthalten.
Preisgestaltung
Die Preise für Aggregationsabfragen hängen von der Anzahl der Indexeinträge ab, die mit der Abfrage übereinstimmen. Für eine große Anzahl übereinstimmender Einträge wird Ihnen eine geringe Anzahl an Lesevorgängen berechnet.
Weitere detaillierte Preisinformationen finden Sie hier.