Catch up on highlights from Firebase at Google I/O 2023. Learn more

使用聚合查詢計數文檔

聚合查詢處理來自多個索引條目的數據以返回單個匯總值。

Cloud Firestore 支持count()聚合查詢。 count()允許您確定集合或查詢中的文檔數。服務器計算計數,並僅將結果(一個整數)傳輸回您的應用程序,與執行完整查詢相比,節省了計費文檔讀取和傳輸的字節數。

聚合查詢依賴於您的查詢已使用的現有索引配置,並根據掃描的索引條目數按比例縮放。這意味著中小型數據集的聚合在 20-40 毫秒內執行,儘管延遲會隨著計數的項目數量的增加而增加。

使用count()聚合

參考我們在獲取數據中設置的示例數據。

以下count()聚合返回cities集合中的城市總數。

Web modular API

const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
迅速
注意:此產品不適用於 watchOS 和 App Clip 目標。
let query = db.collection("cities")
let countQuery = query.count
do {
    let snapshot = try await countQuery.getAggregation(source: .server)
    print(snapshot.count)
} catch {
    print(error);
}
目標-C
注意:此產品不適用於 watchOS 和 App Clip 目標。
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());
      
節點.js
const collectionRef = db.collection('cities');
const snapshot = await collectionRef.count().get();
console.log(snapshot.data().count);
      

count()聚合考慮了查詢中的任何過濾器和任何limit子句。例如,以下聚合返回state等於CA的城市數。

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);
迅速
注意:此產品不適用於 watchOS 和 App Clip 目標。
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);
}
目標-C
注意:此產品不適用於 watchOS 和 App Clip 目標。
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());
      
節點.js
const collectionRef = db.collection('cities');
const query = collectionRef.where('state', '==', 'CA');
const snapshot = await query.count().get();
console.log(snapshot.data().count);
      

Cloud Firestore 安全規則對count()聚合查詢的作用與對返回文檔的普通查詢的作用相同。換句話說,當且僅當您的規則允許客戶端執行某些集合或集合組查詢時,客戶端還可以對這些查詢執行count()聚合。詳細了解Cloud Firestore 安全規則如何與查詢交互

限制

請注意count()聚合查詢的以下限制:

  • count()聚合查詢目前僅通過直接服務器響應支持。查詢僅由 Cloud Firestore 後端提供,跳過本地緩存和任何緩衝更新。此行為與在Cloud Firestore 事務中執行的操作相同。您目前不能將count()查詢與實時偵聽器和離線查詢一起使用。

  • 如果count()聚合無法在 60 秒內解決,它會返回DEADLINE_EXCEEDED錯誤。性能取決於您的索引配置和數據集的大小。

    如果無法在 60 秒期限內完成操作,可能的解決方法是對大型數據集使用計數器

  • count()聚合從索引條目中讀取並僅計算索引字段。

  • 在查詢中添加OrderBy子句將計數限制為存在排序字段的文檔。

價錢

count()的定價取決於查詢匹配的索引條目數。您需要為大量匹配條目支付少量閱讀費用。

查看更詳細的定價信息