Firebase Summit のすべての発表内容に目を通し、Firebase を活用してアプリ開発を加速し、自信を持ってアプリを実行できる方法をご確認ください。 詳細

集計クエリを使用してドキュメントをカウントする

コレクションでコンテンツを整理 必要に応じて、コンテンツの保存と分類を行います。

集計クエリは、複数のインデックス エントリからのデータを処理して、1 つの集計値を返します。

Cloud Firestore はcount()集計クエリをサポートしています。 count()を使用すると、コレクションまたはクエリ内のドキュメントの数を確認できます。サーバーはカウントを計算し、結果 (単一の整数) のみをアプリに送信します。これにより、完全なクエリを実行する場合と比較して、請求されるドキュメントの読み取りと転送されるバイト数の両方が節約されます。

集計クエリは、クエリが既に使用している既存のインデックス構成に依存し、スキャンされたインデックス エントリの数に比例してスケーリングします。これは、小規模から中規模のデータ セットの集計が 20 ~ 40 ミリ秒以内に実行されることを意味しますが、カウントされるアイテムの数に応じて待機時間が長くなります。

count()集計を使用する

データの取得 で設定したサンプルデータを参照してください。

次のcount()集計は、 citiesコレクション内の都市の総数を返します。

Web version 9

const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
    
迅速
let collection = db.collection("cities")
let countQuery = collection.count
do {
  let snapshot = try await countQuery.getAggregation(source: .server)
  print(snapshot.count)
} catch {
  print(error);
}
      
Objective-C
FIRCollectionReference* collection = [db collectionWithPath:@"cities"];
[collection.count
  aggregationWithSource:FIRAggregateSourceServer
  completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) {
    if (error == nil) {
        NSLog(@"Cities count: %@", snapshot.count);
    } else {
        NSLog(@"Error fetching count: %@", error);
    }
  }
];
      

Kotlin+KTX

val collection = db.collection("cities")
val countQuery = collection.count()
countQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
  if (task.isSuccessful) {
    val snapshot = task.result
    Log.d(TAG, "Count: ${snapshot.count}")
  } else {
    Log.d(TAG, "Count failed: ", task.getException())
  }
}
      

Java

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());
  }
});
      
ジャワ
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句が考慮されます。たとえば、次の集計は、 stateCAと等しい都市の数を返します。

Web version 9

const coll = collection(db, "cities");
const query_ = query(coll, where('state', '==', 'CA'));
const snapshot = await getCountFromServer(query_);
console.log('count: ', snapshot.data().count);
    
迅速
let collection = db.collection("cities")
let query = collection.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
FIRCollectionReference* collection = [db collectionWithPath:@"cities"];
FIRQuery* query = [collection queryWhereField:@"state" isEqualTo:@"CA"];
[query.count
  aggregationWithSource:FIRAggregateSourceServer
  completion:^(FIRAggregateQuerySnapshot *snapshot, NSError *error) {
    if (error == nil) {
        NSLog(@"Cities count: %@", snapshot.count);
    } else {
        NSLog(@"Error fetching count: %@", error);
    }
  }
];
      

Kotlin+KTX

val collection = db.collection("cities")
val query = collection.whereEqualTo("state", "CA")
val countQuery = query.count()
countQuery.get(AggregateSource.SERVER).addOnCompleteListener { task ->
  if (task.isSuccessful) {
    val snapshot = task.result
    Log.d(TAG, "Count: ${snapshot.count}")
  } else {
    Log.d(TAG, "Count failed: ", task.getException())
  }
}
      

Java

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());
  }
});
      
ジャワ
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);
      

Cloud Firestore セキュリティ ルールは、 count()集計クエリに対して、ドキュメントを返す通常のクエリと同じように機能します。つまり、ルールでクライアントが特定のコレクションまたはコレクション グループのクエリを実行できる場合に限り、クライアントはそれらのクエリに対してcount()集計を実行することもできます。 Cloud Firestore セキュリティ ルールがクエリとどのように相互作用するかについては、こちらをご覧ください。

制限事項

count()集計クエリに関する次の制限に注意してください。

  • count()集計クエリは、現在、ダイレクト サーバー レスポンス経由でのみサポートされています。クエリは Cloud Firestore バックエンドによってのみ処理され、ローカル キャッシュとバッファリングされた更新はスキップされます。この動作は、 Cloud Firestore トランザクション内で実行される操作と同じです。現在、リアルタイム リスナーおよびオフライン クエリでcount()クエリを使用することはできません。

  • count()集計が 60 秒以内に解決できない場合、 DEADLINE_EXCEEDEDエラーが返されます。パフォーマンスは、インデックスの構成とデータセットのサイズによって異なります。

    60 秒の期限内に操作を完了できない場合、考えられる回避策は、大きなデータ セット用のカウンターを使用することです。

  • count()集計は、インデックス エントリから読み取り、インデックス付きフィールドのみをカウントします。

  • クエリにOrderBy句を追加すると、並べ替えプロパティが存在するエンティティにカウントが制限されます。

価格

count()の料金は、クエリに一致するインデックス エントリの数によって異なります。多数の一致したエントリに対して、少数の読み取りに対して課金されます。

詳細な価格情報を参照してください。