שאילתת צבירת נתונים מעבדת את הנתונים מכמה רשומות במדד כדי להחזיר ערך סיכום יחיד.
Cloud Firestore תומך בשאילתות הסיכום הבאות:
count()
sum()
average()
Cloud Firestore מחשב את הצבירה ומעביר רק את התוצאה חזרה לאפליקציה. בהשוואה להרצת שאילתה מלאה וחישוב הצבירה באפליקציה, שאילתות צבירה חוסכות גם בקריאת מסמכים לחיוב וגם בבייטים המועברים.
שאילתות צבירת נתונים מסתמכות על הגדרת האינדקס הקיימת שכבר משמשת את השאילתות, והן מותאמות באופן יחסי למספר הרשומות שנסרקות באינדקס. זמן האחזור עולה ככל שמספר הפריטים בצבירה גדל.
שימוש בנתוני הצבירה count()
שאילתת הצבירה count()
מאפשרת לקבוע את מספר המסמכים באוסף או בשאילתה.
מידע נוסף על נתוני הדוגמה זמין במאמר קבלת נתונים.
חלוקת הערכים של count()
מחזירה את המספר הכולל של הערים באוסף cities
.
Web
const coll = collection(db, "cities"); const snapshot = await getCountFromServer(coll); console.log('count: ', snapshot.data().count);
Swift
let query = db.collection("cities") let countQuery = query.count do { let snapshot = try await countQuery.getAggregation(source: .server) print(snapshot.count) } catch { print(error) }
Objective-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("cities").count().get().then( (res) => print(res.count), onError: (e) => print("Error completing: $e"), );
Go
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
הצבירה count()
משקללת את המסננים שבשאילתה ואת כל תנאי limit
.
Web
const coll = collection(db, "cities"); const q = query(coll, where("state", "==", "CA")); const snapshot = await getCountFromServer(q); console.log('count: ', snapshot.data().count);
Swift
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) }
Objective-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 collection queries. db.collection("cities").where("capital", isEqualTo: 10).count().get().then( (res) => print(res.count), onError: (e) => print("Error completing: $e"), );
Go
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
שימוש בצבירה sum()
אפשר להשתמש בצבירה sum()
כדי להחזיר את הסכום הכולל של ערכים מספריים שתואמים לשאילתה נתונה. לדוגמה:
Web
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { totalPopulation: sum('population') }); console.log('totalPopulation: ', snapshot.data().totalPopulation);
Swift
let query = db.collection("cities") let aggregateQuery = query.aggregate([AggregateField.sum("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print(snapshot.get(AggregateField.sum("population"))) } catch { print(error) }
Objective-C
FIRQuery *query = [self.db collectionWithPath:@"cities"]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForSumOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]); } }];
Java
Query query = db.collection("cities"); AggregateQuery aggregateQuery = query.aggregate(AggregateField.sum("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities") val aggregateQuery = query.aggregate(AggregateField.sum("population")) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Dart
db.collection("cities").aggregate(sum("population")).get().then( (res) => print(res.getAverage("population")), onError: (e) => print("Error completing: $e"), );
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);
Python
collection_ref = client.collection("users") aggregate_query = aggregation.AggregationQuery(collection_ref) aggregate_query.sum("coins", alias="sum") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Sum of results from query: {result[0].value}")
Go
func createSumQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850) aggregationQuery := query.NewAggregationQuery().WithSum("coins", "sum_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } sum, ok := results["sum_coins"] if !ok { return errors.New("firestore: couldn't get alias for SUM from results") } sumValue := sum.(*firestorepb.Value) fmt.Fprintf(w, "Sum of results from query: %d\n", sumValue.GetIntegerValue()) return nil }
הסכום המצטבר של sum()
מתייחס לכל המסננים בשאילתה וכל תנאי המגבלה – לדוגמה:
Web
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);
Swift
let query = db.collection("cities").whereField("capital", isEqualTo: true) let aggregateQuery = query.aggregate([AggregateField.sum("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print(snapshot.get(AggregateField.sum("population"))) } catch { print(error) }
Objective-C
FIRQuery *query = [[self.db collectionWithPath:@"cities"] queryWhereFilter:[FIRFilter filterWhereField:@"capital" isEqualTo:@YES]]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForSumOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]); } }];
Java
Query query = db.collection("cities").whereEqualTo("capital", true); AggregateQuery aggregateQuery = query.aggregate(AggregateField.sum("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities").whereEqualTo("capital", true) val aggregateQuery = query.aggregate(AggregateField.sum("population")) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Dart
db .collection("cities") .where("capital", isEqualTo: true) .aggregate(sum("population")) .get() .then( (res) => print(res.getAverage("population")), onError: (e) => print("Error completing: $e"), );
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);
Python
collection_ref = client.collection("users") query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew")) aggregate_query = aggregation.AggregationQuery(query) aggregate_query.sum("coins", alias="sum") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Sum of results from query: {result[0].value}")
Go
func createSumQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850).Limit(5) aggregationQuery := query.NewAggregationQuery().WithSum("coins", "sum_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } sum, ok := results["sum_coins"] if !ok { return errors.New("firestore: couldn't get alias for SUM from results") } sumValue := sum.(*firestorepb.Value) fmt.Fprintf(w, "Sum of results from query: %d\n", sumValue.GetIntegerValue()) return nil }
שימוש בנתוני הצבירה average()
אפשר להשתמש בצבירה average()
כדי להחזיר את הממוצע של ערכים מספריים שתואמים לשאילתה נתונה, לדוגמה:
Web
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { averagePopulation: average('population') }); console.log('averagePopulation: ', snapshot.data().averagePopulation);
Swift
let query = db.collection("cities") let aggregateQuery = query.aggregate([AggregateField.average("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print(snapshot.get(AggregateField.average("population"))) } catch { print(error) }
Objective-C
FIRQuery *query = [self.db collectionWithPath:@"cities"]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]); } }];
Java
Query query = db.collection("cities"); AggregateQuery aggregateQuery = query.aggregate(AggregateField.average("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities") val aggregateQuery = query.aggregate(AggregateField.average("population")) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Dart
db.collection("cities").aggregate(average("population")).get().then( (res) => print(res.getAverage("population")), onError: (e) => print("Error completing: $e"), );
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);
Python
collection_ref = client.collection("users") aggregate_query = aggregation.AggregationQuery(collection_ref) aggregate_query.avg("coins", alias="avg") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Average of results from query: {result[0].value}")
Go
func createAvgQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850) aggregationQuery := query.NewAggregationQuery().WithAvg("coins", "avg_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } avg, ok := results["avg_coins"] if !ok { return errors.New("firestore: couldn't get alias for AVG from results") } avgValue := avg.(*firestorepb.Value) fmt.Fprintf(w, "Avg of results from query: %d\n", avgValue.GetDoubleValue()) return nil }
הסכום המצטבר של average()
מתייחס לכל המסננים בשאילתה וכל תנאי המגבלה, לדוגמה:
Web
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);
Swift
let query = db.collection("cities").whereField("capital", isEqualTo: true) let aggregateQuery = query.aggregate([AggregateField.average("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print(snapshot.get(AggregateField.average("population"))) } catch { print(error) }
Objective-C
FIRQuery *query = [[self.db collectionWithPath:@"cities"] queryWhereFilter:[FIRFilter filterWhereField:@"capital" isEqualTo:@YES]]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]); } }];
Java
Query query = db.collection("cities").whereEqualTo("capital", true); AggregateQuery aggregateQuery = query.aggregate(AggregateField.average("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities").whereEqualTo("capital", true) val aggregateQuery = query.aggregate(AggregateField.average("population")) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Dart
db .collection("cities") .where("capital", isEqualTo: true) .aggregate(average("population")) .get() .then( (res) => print(res.getAverage("population")), onError: (e) => print("Error completing: $e"), );
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);
Python
collection_ref = client.collection("users") query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew")) aggregate_query = aggregation.AggregationQuery(query) aggregate_query.avg("coins", alias="avg") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Average of results from query: {result[0].value}")
Go
func createAvgQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850).Limit(5) aggregationQuery := query.NewAggregationQuery().WithAvg("coins", "avg_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } avg, ok := results["avg_coins"] if !ok { return errors.New("firestore: couldn't get alias for AVG from results") } avgValue := avg.(*firestorepb.Value) fmt.Fprintf(w, "Avg of results from query: %d\n", avgValue.GetDoubleValue()) return nil }
חישוב כמה צבירות בשאילתה
אפשר לשלב כמה צבירות בצינור עיבוד נתונים אחד של צבירת נתונים. כך אפשר לצמצם את מספר הקריאות של האינדקס הנדרשות. אם השאילתה כוללת צבירת נתונים במספר שדות, יכול להיות שיידרש אינדקס מורכב מהשאילתה. במקרה כזה, Cloud Firestore מציע אינדקס.
הדוגמה הבאה מבצעת כמה צבירת נתונים בשאילתת צבירה אחת:
Web
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);
Swift
let query = db.collection("cities") let aggregateQuery = query.aggregate([ AggregateField.count(), AggregateField.sum("population"), AggregateField.average("population")]) do { let snapshot = try await aggregateQuery.getAggregation(source: .server) print("Count: \(snapshot.get(AggregateField.count()))") print("Sum: \(snapshot.get(AggregateField.sum("population")))") print("Average: \(snapshot.get(AggregateField.average("population")))") } catch { print(error) }
Objective-C
FIRQuery *query = [self.db collectionWithPath:@"cities"]; FIRAggregateQuery *aggregateQuery = [query aggregate:@[ [FIRAggregateField aggregateFieldForCount], [FIRAggregateField aggregateFieldForSumOfField:@"population"], [FIRAggregateField aggregateFieldForAverageOfField:@"population"]]]; [aggregateQuery aggregationWithSource:FIRAggregateSourceServer completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) { if (error != nil) { NSLog(@"Error fetching aggregate: %@", error); } else { NSLog(@"Count: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForCount]]); NSLog(@"Sum: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForSumOfField:@"population"]]); NSLog(@"Avg: %@", [snapshot valueForAggregateField:[FIRAggregateField aggregateFieldForAverageOfField:@"population"]]); } }];
Java
Query query = db.collection("cities"); AggregateQuery aggregateQuery = query.aggregate( AggregateField.count(), AggregateField.sum("population"), AggregateField.average("population")); aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener(new OnCompleteListener<AggregateQuerySnapshot>() { @Override public void onComplete(@NonNull Task<AggregateQuerySnapshot> task) { if (task.isSuccessful()) { // Aggregate fetched successfully AggregateQuerySnapshot snapshot = task.getResult(); Log.d(TAG, "Count: " + snapshot.get(AggregateField.count())); Log.d(TAG, "Sum: " + snapshot.get(AggregateField.sum("population"))); Log.d(TAG, "Average: " + snapshot.get(AggregateField.average("population"))); } else { Log.d(TAG, "Aggregation failed: ", task.getException()); } } });
Kotlin+KTX
val query = db.collection("cities") val aggregateQuery = query.aggregate( AggregateField.count(), AggregateField.sum("population"), AggregateField.average("population") ) aggregateQuery.get(AggregateSource.SERVER).addOnCompleteListener { task -> if (task.isSuccessful) { // Aggregate fetched successfully val snapshot = task.result Log.d(TAG, "Count: ${snapshot.get(AggregateField.count())}") Log.d(TAG, "Sum: ${snapshot.get(AggregateField.sum("population"))}") Log.d(TAG, "Average: ${snapshot.get(AggregateField.average("population"))}") } else { Log.d(TAG, "Aggregate failed: ", task.getException()) } }
Dart
db .collection("cities") .aggregate( count(), sum("population"), average("population"), ) .get() .then( (res) { print(res.count); print(res.getSum("population")); print(res.getAverage("population")); }, onError: (e) => print("Error completing: $e"), );
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);
Python
collection_ref = client.collection("users") query = collection_ref.where(filter=FieldFilter("people", "==", "Matthew")) aggregate_query = aggregation.AggregationQuery(query) aggregate_query.sum("coins", alias="sum").avg("coins", alias="avg") results = aggregate_query.get() for result in results: print(f"Alias of results from query: {result[0].alias}") print(f"Aggregation of results from query: {result[0].value}")
Go
func createMultiAggregationQuery(w io.Writer, projectID string) error { ctx := context.Background() client, err := firestore.NewClient(ctx, projectID) if err != nil { return err } defer client.Close() collection := client.Collection("users") query := collection.Where("born", ">", 1850) aggregationQuery := query.NewAggregationQuery().WithCount("count").WithSum("coins", "sum_coins").WithAvg("coins", "avg_coins") results, err := aggregationQuery.Get(ctx) if err != nil { return err } }
שאילתות עם כמה צבירויות כוללות רק את המסמכים שמכילים את כל השדות בכל צבירות. כתוצאה מכך, ביצוע כל צבירת נתונים בנפרד עשוי להוביל לתוצאות שונות.
כללי אבטחה לשאילתות צבירת נתונים
Cloud Firestore Security Rules פועלות באותו אופן בשאילתות צבירת נתונים ובשאילתות שמחזירות מסמכים. במילים אחרות, אם ורק אם הכללים שלכם מאפשרים ללקוחות להפעיל שאילתות מסוימות של איסוף או של קבוצות אוספים, הלקוחות יוכלו גם לבצע את הצבירה בשאילתות האלה. מידע נוסף על האינטראקציה של Cloud Firestore Security Rules עם שאילתות
התנהגות ומגבלות
כשעובדים עם שאילתות צבירת נתונים, חשוב לשים לב להתנהגות ולמגבלות הבאות:
לא ניתן להשתמש בשאילתות צבירה עם מאזינים בזמן אמת ובשאילתות אופליין. יש תמיכה בשאילתות צבירת נתונים רק באמצעות תגובה ישירה מהשרת. השאילתות מוצגות רק על ידי הקצה העורפי של Cloud Firestore, בלי לעבור דרך המטמון המקומי וכל עדכון שנשמר במאגר. ההתנהגות הזו זהה לפעולות שמבוצעות בתוךCloud Firestore עסקאות.
אם לא ניתן לפתור צבירה תוך 60 שניות, תוחזר שגיאה מסוג
DEADLINE_EXCEEDED
. הביצועים תלויים בהגדרת האינדקס ובגודל של מערך הנתונים.אם אי אפשר להשלים את הפעולה בתוך 60 שניות, אפשר להשתמש במספרים עוקבים למערכי נתונים גדולים.
שאילתות צבירת נתונים נקראות מרשומות במדד וכוללות רק שדות שנוספו לאינדקס.
הוספת תנאי
OrderBy
לשאילתת צבירה מגבילה את הצבירה למסמכים שבהם קיים שדה המיון.בצבירה של
sum()
ו-average()
, המערכת מתעלמת מערכים לא מספריים. בצבירותsum()
ו-average()
נלקחים בחשבון רק ערכים שלמים וערכים של מספרים בנקודה צפה.כשמשלבים צבירות מרובות בשאילתה אחת, שימו לב ש-
sum()
ו-average()
מתעלמים מערכים לא מספריים, ואילוcount()
כולל ערכים לא מספריים.אם משלבים צבירות שנמצאות בשדות שונים, החישוב כולל רק את המסמכים שמכילים את כל השדות האלה.
תמחור
התמחור של שאילתות צבירת נתונים תלוי במספר רשומות האינדקס שהשאילתה תואמת להן. אתם מחויבים על מספר קטן של קריאות עבור מספר גדול של רשומות תואמות. אתם מחויבים על פעולת קריאה אחת לכל קבוצה של עד 1,000 רשומות באינדקס שנקראות.
מידע נוסף על התמחור של שאילתות צבירת נתונים זמין במאמר שאילתות צבירת נתונים.