يعالج استعلام التجميع البيانات من إدخالات فهارس متعددة لعرض قيمة موجزة واحدة.
يتيح 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
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
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
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
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
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()
في الاعتبار أي فلاتر في طلب البحث وأي عبارات limit
، على سبيل المثال:
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
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
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 إدخال.
لمزيد من المعلومات حول أسعار طلبات البحث المجمّعة، يمكنك الاطّلاع على طلبات البحث المجمّعة.