聚合查詢處理來自多個索引條目的資料以傳回單一總計值。
Cloud Firestore 支援以下聚合查詢:
-
count()
-
sum()
-
average()
Cloud Firestore 計算聚合並僅將結果傳回您的應用程式。與在應用程式中執行完整查詢和計算聚合相比,聚合查詢可以節省計費文件讀取和傳輸位元組數。
聚合查詢依賴您的查詢已使用的現有索引配置,並根據掃描的索引條目數按比例縮放。延遲隨著聚合中項目數量的增加而增加。
使用count()
聚合
count()
聚合查詢可讓您確定集合或查詢中的文件數量。
請參閱我們在取得資料中設定的範例資料。
以下count()
聚合傳回cities
集合中的城市總數。
Web modular API
const coll = collection(db, "cities"); const snapshot = await getCountFromServer(coll); console.log('count: ', snapshot.data().count);
迅速
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("users").count().get().then( (res) => print(res.count), onError: (e) => print("Error completing: $e"), );
去
爪哇
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 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);
迅速
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 collectionGroup queries. db.collection("users").where("age", isGreaterThan: 10).count().get().then( (res) => print(res.count), onError: (e) => print("Error completing: $e"), );
去
爪哇
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 modular API
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { totalPopulation: sum('population') }); console.log('totalPopulation: ', snapshot.data().totalPopulation);
爪哇
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);
sum()
聚合考慮了查詢上的任何篩選器和任何限制子句,例如:
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);
爪哇
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);
使用average()
聚合
使用average()
聚合傳回與給定查詢相符的數值的平均值,例如:
Web modular API
const coll = collection(firestore, 'cities'); const snapshot = await getAggregateFromServer(coll, { averagePopulation: average('population') }); console.log('averagePopulation: ', snapshot.data().averagePopulation);
爪哇
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);
average()
聚合考慮了查詢上的任何篩選器和任何限制子句,例如:
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);
爪哇
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);
計算查詢中的多個聚合
您可以在單一聚合管道中組合多個聚合。這可以減少所需的索引讀取次數。如果查詢包含多個欄位的聚合,則查詢可能需要複合索引。在這種情況下,Cloud Firestore 建議使用索引。
以下範例在單一聚合查詢中執行多個聚合:
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);
爪哇
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);
具有多個聚合的查詢僅包含包含每個聚合中所有欄位的文件。這可能會導致單獨執行每個聚合產生不同的結果。
聚合查詢的安全規則
Cloud Firestore 安全性規則在聚合查詢上的運作方式與在傳回文件的查詢上的工作方式相同。換句話說,當且僅當您的規則允許客戶端執行某些集合或集合組查詢時,客戶端也可以對這些查詢執行聚合。詳細了解Cloud Firestore 安全規則如何與查詢互動。
行為和限制
使用聚合查詢時,請注意以下行為和限制:
您不能將聚合查詢與即時偵聽器和離線查詢一起使用。僅透過直接伺服器回應支援聚合查詢。查詢僅由 Cloud Firestore 後端提供服務,跳過本機快取和任何緩衝的更新。此行為與Cloud Firestore 事務內執行的操作相同。
如果聚合無法在 60 秒內解析,則會傳回
DEADLINE_EXCEEDED
錯誤。效能取決於您的索引配置和資料集的大小。如果操作無法在 60 秒期限內完成,可能的解決方法是對大型資料集使用計數器。
聚合查詢從索引條目中讀取,並且僅包含索引欄位。
在聚合查詢中新增
OrderBy
子句會將聚合限制為存在排序欄位的文件。對於
sum()
和average()
聚合,非數字值將被忽略。sum()
和average()
聚合僅考慮整數值和浮點數值。在單一查詢中組合多個聚合時,請注意
sum()
和average()
忽略非數字值,而count()
包含非數字值。如果您組合不同欄位上的聚合,則計算僅包括包含所有這些欄位的文件。
價錢
聚合查詢的定價取決於查詢匹配的索引條目的數量。您需要為大量匹配的條目支付少量的讀取費用。
查看更詳細的定價資訊。