Truy vấn tổng hợp xử lý dữ liệu từ nhiều mục nhập chỉ mục để trả về một giá trị tóm tắt duy nhất.
Cloud Firestore hỗ trợ các truy vấn tổng hợp sau:
count()
sum()
average()
Cloud Firestore tính toán dữ liệu tổng hợp và chỉ truyền kết quả trở lại ứng dụng của bạn. So với việc thực thi một truy vấn đầy đủ và tính toán tổng hợp trong ứng dụng, truy vấn tổng hợp sẽ tiết kiệm cả số lượt đọc tài liệu đã tính phí và số byte được chuyển.
Truy vấn tổng hợp dựa vào cấu hình chỉ mục hiện có mà truy vấn của bạn đã sử dụng và mở rộng theo tỷ lệ với số mục nhập chỉ mục được quét. Độ trễ tăng theo số lượng mục trong dữ liệu tổng hợp.
Sử dụng tính năng tổng hợp count()
Truy vấn tổng hợp count()
cho phép bạn xác định số lượng tài liệu trong một bộ sưu tập hoặc truy vấn.
Để biết thêm thông tin về dữ liệu mẫu, hãy xem phần Nhận dữ liệu.
Phương thức tổng hợp count()
sau đây trả về tổng số thành phố trong tập hợp 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"), );
Tiến hành
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
Tính năng tổng hợp count()
sẽ tính đến mọi bộ lọc trên truy vấn và mọi mệnh đề 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"), );
Tiến hành
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
Sử dụng dữ liệu tổng hợp sum()
Sử dụng hàm tổng hợp sum()
để trả về tổng giá trị số khớp với một truy vấn nhất định, ví dụ:
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}")
Tiến hành
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 }
Tính năng tổng hợp sum()
sẽ tính đến mọi bộ lọc trên truy vấn và mọi mệnh đề giới hạn, ví dụ:
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}")
Tiến hành
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 }
Sử dụng dữ liệu tổng hợp average()
Sử dụng hàm tổng hợp average()
để trả về giá trị trung bình của các giá trị số khớp với một truy vấn nhất định, ví dụ:
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}")
Tiến hành
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 }
Tính năng tổng hợp average()
sẽ tính đến mọi bộ lọc trên truy vấn và mọi mệnh đề giới hạn, ví dụ:
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}")
Tiến hành
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 }
Tính toán nhiều phép tổng hợp trong một truy vấn
Bạn có thể kết hợp nhiều phép tổng hợp trong một quy trình tổng hợp. Điều này có thể giảm số lần đọc chỉ mục cần thiết. Nếu truy vấn bao gồm các phép tổng hợp trên nhiều trường, thì truy vấn đó có thể yêu cầu chỉ mục tổng hợp. Trong trường hợp đó, Cloud Firestore sẽ đề xuất một chỉ mục.
Ví dụ sau đây thực hiện nhiều quá trình tổng hợp trong một truy vấn tổng hợp:
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}")
Tiến hành
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 } }
Các truy vấn có nhiều phép tổng hợp chỉ bao gồm những tài liệu chứa tất cả các trường trong mỗi phép tổng hợp. Điều này có thể dẫn đến kết quả khác nhau so với việc thực hiện từng phép tổng hợp riêng biệt.
Quy tắc bảo mật cho truy vấn tổng hợp
Cloud Firestore Security Rules hoạt động giống nhau trên các truy vấn tổng hợp cũng như trên các truy vấn trả về tài liệu. Nói cách khác, nếu và chỉ khi quy tắc của bạn cho phép ứng dụng thực thi một số truy vấn bộ sưu tập hoặc nhóm bộ sưu tập nhất định, thì ứng dụng cũng có thể thực hiện việc tổng hợp trên các truy vấn đó. Tìm hiểu thêm về cách Cloud Firestore Security Rules tương tác với các truy vấn.
Hành vi và giới hạn
Khi bạn làm việc với các truy vấn tổng hợp, hãy lưu ý hành vi và các giới hạn sau:
Bạn không thể sử dụng truy vấn tổng hợp với trình nghe theo thời gian thực và truy vấn ngoại tuyến. Truy vấn tổng hợp chỉ được hỗ trợ thông qua phản hồi trực tiếp của máy chủ. Các truy vấn chỉ được phân phát bởi phần phụ trợ Cloud Firestore, bỏ qua bộ nhớ đệm cục bộ và mọi nội dung cập nhật được lưu vào bộ đệm. Hành vi này giống hệt với các thao tác được thực hiện bên tronggiao dịch Cloud Firestore.
Nếu không thể phân giải trong vòng 60 giây, một mục tổng hợp sẽ trả về lỗi
DEADLINE_EXCEEDED
. Hiệu suất phụ thuộc vào cấu hình chỉ mục và kích thước của tập dữ liệu.Nếu không thể hoàn tất thao tác trong thời hạn 60 giây, thì giải pháp có thể là sử dụng bộ đếm cho các tập dữ liệu lớn.
Truy vấn tổng hợp đọc từ các mục nhập chỉ mục và chỉ bao gồm các trường được lập chỉ mục.
Việc thêm mệnh đề
OrderBy
vào truy vấn tổng hợp sẽ giới hạn việc tổng hợp ở những tài liệu có trường sắp xếp.Đối với các phép tổng hợp
sum()
vàaverage()
, các giá trị không phải số sẽ bị bỏ qua. Các phép tổng hợpsum()
vàaverage()
chỉ tính đến các giá trị số nguyên và giá trị số dấu phẩy động.Khi kết hợp nhiều phép tổng hợp trong một truy vấn, hãy lưu ý rằng
sum()
vàaverage()
bỏ qua các giá trị không phải số, trong khicount()
bao gồm cả các giá trị không phải số.Nếu bạn kết hợp các phép tổng hợp trên các trường khác nhau, thì phép tính sẽ chỉ bao gồm những tài liệu chứa tất cả các trường đó.
Giá
Mức giá cho truy vấn tổng hợp phụ thuộc vào số lượng mục nhập chỉ mục mà truy vấn khớp. Bạn sẽ bị tính phí một số ít lượt đọc cho một số lượng lớn mục nhập khớp. Bạn sẽ bị tính phí một thao tác đọc cho mỗi lô có tối đa 1.000 mục nhập chỉ mục được đọc.
Để biết thêm thông tin về mức giá của truy vấn tổng hợp, hãy xem bài viết Truy vấn tổng hợp.