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 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 hiện một truy vấn đầy đủ và tính toán tổng hợp trong ứng dụng của bạn, các truy vấn tổng hợp sẽ tiết kiệm cả số lần đọc tài liệu được tính phí và số byte được truyền.
Truy vấn tổng hợp dựa trên cấu hình chỉ mục hiện có mà truy vấn của bạn đã sử dụng và chia tỷ lệ tương ứng với số mục nhập chỉ mục được quét. Độ trễ tăng theo số lượng mục trong tập hợp.
Sử dụ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.
Tham khảo dữ liệu mẫu chúng ta thiết lập ở phần Lấy dữ liệu .
Tổng hợp count()
sau đây trả về tổng số thành phố trong bộ sưu tập cities
.
Web modular API
const coll = collection(db, "cities"); const snapshot = await getCountFromServer(coll); console.log('count: ', snapshot.data().count);
Nhanh
let query = db.collection("cities") let countQuery = query.count do { let snapshot = try await countQuery.getAggregation(source: .server) print(snapshot.count) } catch { print(error) }
Mục tiêu-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"), );
Đi
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ập hợp count()
tính đến mọi bộ lọc trên truy vấn và mọi mệnh đề 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);
Nhanh
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) }
Mục tiêu-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"), );
Đi
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 tổng hợp sum()
Sử dụng phép tổng hợp sum()
để trả về tổng tổng các giá trị số khớp với một truy vấn nhất định—ví dụ:
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);
Tập hợp sum()
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 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);
Sử dụng tổng hợp average()
Sử dụng phép 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 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);
Tập hợp average()
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 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);
Tính toán nhiều tập hợp trong một truy vấn
Bạn có thể kết hợp nhiều tập hợp trong một đường dẫn tổng hợp duy nhất. Điều này có thể làm giảm số lần đọc chỉ mục cần thiết. Nếu truy vấn bao gồm các tập 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 đề xuất một chỉ mục.
Ví dụ sau đây thực hiện nhiều tập hợp trong một truy vấn tổng hợp duy nhất:
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);
Truy vấn có nhiều tập hợp chỉ bao gồm các tài liệu chứa tất cả các trường trong mỗi tập hợp. Điều này có thể dẫn đến các kết quả khác 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
Quy tắc bảo mật của Cloud Firestore hoạt động tương tự 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ỉ nếu quy tắc của bạn cho phép khách hàng thực hiện một số truy vấn bộ sưu tập hoặc nhóm bộ sưu tập nhất định thì khách hàng cũng có thể thực hiện tổng hợp các truy vấn đó. Tìm hiểu thêm về cách Quy tắc bảo mật của Cloud Firestore tương tác với truy vấn .
Hành vi và hạn chế
Khi bạn làm việc với các truy vấn tổng hợp, hãy lưu ý các hành vi và hạn chế sau:
Bạn không thể sử dụng truy vấn tổng hợp với trình nghe 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ục vụ bởi chương trình phụ trợ của Cloud Firestore, bỏ qua bộ nhớ đệm cục bộ và mọi bản cập nhật được lưu vào bộ đệm. Hành vi này giống hệt với các hoạt động được thực hiện bên trong các giao dịch Cloud Firestore .
Nếu một tập hợp không thể giải quyết trong vòng 60 giây thì nó sẽ trả về lỗi
DEADLINE_EXCEEDED
. Hiệu suất phụ thuộc vào cấu hình chỉ mục của bạn và kích thước của tập dữ liệu.Nếu thao tác không thể hoàn thành trong thời hạn 60 giây, giải pháp khả thi 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 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 đối với các tài liệu có trường sắp xếp tồn tại.Đối với tổng hợp
sum()
vàaverage()
, các giá trị không phải là số sẽ bị bỏ qua. 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 tập 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 là số trong khicount()
bao gồm các giá trị không phải là số.Nếu bạn kết hợp các tập hợp trên các trường khác nhau thì phép tính chỉ bao gồm các tài liệu chứa tất cả các trường đó.
Định giá
Giá cho các truy vấn tổng hợp phụ thuộc vào số lượng mục nhập chỉ mục phù hợp với truy vấn. Bạn bị tính phí một số lần đọc nhỏ cho một số lượng lớn các mục nhập trùng khớp.
Xem thêm thông tin giá cả chi tiết.