使用集合让一切井井有条 根据您的偏好保存内容并对其进行分类。

使用汇总查询计数文档

聚合查询会处理多个索引条目中的数据,然后返回单个摘要值。

Firestore 支持 count() 聚合查询。count() 可用于确定集合或查询中的文档数量。服务器会计算数量并且只是将结果(即一个整数)传回您的应用,而不会执行完整的查询,这样做既节省了文档读取费用,又减少了所需传输的字节数。

聚合查询依赖于您的查询已在使用的现有索引配置,并且会根据扫描到的索引条目数量按比例进行扩缩。这意味着,中小规模数据集的聚合过程通常会在 20-40 毫秒内完成,但延迟时间会随着计数项的数量增多而增加。

使用 count() 聚合

请参阅我们在获取数据部分中设置的示例数据。

以下 count() 聚合会返回 cities 集合中的城市总数。

Web 版本 9

const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
Swift
注意:此产品不适用于 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);
}
Objective-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
Android
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
Android
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())
    }
}
Java
Android
CollectionReference collection = db.collection("cities");
AggregateQuery countQuery = collection.count();
countQuery.get(AggregateSource.SERVER).addOnCompleteListener(task -> {
  if (task.isSuccessful()) {
    AggregateQuerySnapshot snapshot = task.getResult();
    Log.d(TAG, "Count: " + snapshot.getCount());
  } else {
    Log.d(TAG, "Count failed: ", task.getException());
  }
});
      
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);
      

count() 聚合会考虑查询的所有过滤条件以及所有 limit 子句。例如,以下聚合会返回 state 设为 CA 时的城市数量。

Web 版本 9

const coll = collection(db, "cities");
const q = query(coll, where("state", "==", "CA"));
const snapshot = await getCountFromServer(q);
console.log('count: ', snapshot.data().count);
Swift
注意:此产品不适用于 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);
}
Objective-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
Android
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
Android
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())
    }
}
Java
Android
CollectionReference collection = db.collection("cities");
Query query = collection.whereEqualTo("state", "CA");
AggregateQuery countQuery = query.count();
countQuery.get(AggregateSource.SERVER).addOnCompleteListener(task -> {
  if (task.isSuccessful()) {
    AggregateQuerySnapshot snapshot = task.getResult();
    Log.d(TAG, "Count: " + snapshot.getCount());
  } else {
    Log.d(TAG, "Count failed: ", task.getException());
  }
});
      
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);
      

Firestore 安全规则在 count() 汇总查询中的工作方式与返回文档的常规查询相同。换句话说,当且仅当您的规则允许客户端执行某些集合或合集组查询时,客户端也可以对这些查询执行 count() 聚合操作。详细了解 Firestore 安全规则如何与查询交互

限制

请注意,count() 聚合查询存在以下限制:

  • count() 聚合查询目前只能通过直接服务器响应进行处理。查询将仅由 Firestore 后端提供,跳过本地缓存和任何缓冲的更新。此行为与 Firestore 事务中执行的操作相同。您目前无法将 count() 查询与实时监听器和离线查询搭配使用。

  • 如果 count() 聚合无法在 60 秒内完成解析,则会返回 DEADLINE_EXCEEDED 错误。聚合性能取决于您的索引配置以及数据集的规模。

    如果操作无法在 60 秒时限内完成,作为一种可能的解决方法,您可以针对大规模数据集使用计数器

  • count() 聚合会从索引条目中读取数据,并且只对编入索引的字段进行计数。

  • 如果向查询添加 OrderBy 子句,则查询只会对存在排序属性的实体进行计数。

价格

count() 的价格取决于查询匹配的索引条目的数量。您需要为大量匹配的条目支付少量读取费用。

查看更详细的价格信息