集約クエリは、複数のインデックス エントリのデータを処理して、1 つのサマリー値を返します。
Cloud Firestore は次の集約クエリをサポートしています。
count()
sum()
average()
Cloud Firestore は集計を算出し、結果のみをアプリに返します。完全なクエリを実行してアプリで集計を計算する場合と比較して、集約クエリは、課金されるドキュメントの読み取り数と転送されたバイト数の両方を節約します。
集約クエリは、クエリですでに使用している既存のインデックス構成を使用し、またスキャンされるインデックス エントリの数に比例してスケーリングされます。レイテンシは、集計のアイテム数とともに増加します。
count()
集約を使用する
count()
集計クエリを使用すると、コレクションまたはクエリ内のドキュメント数を決定できます。
データの取得で設定したサンプルデータをご覧ください。
次の count()
集約は、cities
コレクション内の都市の総数を返します。
ウェブ向けのモジュラー API
const coll = collection(db, "cities"); const snapshot = await getCountFromServer(coll); console.log('count: ', snapshot.data().count);
Swift
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"), );
Go
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
count()
集約では、クエリに対するフィルタと、limit
句が考慮されます。
ウェブ向けのモジュラー API
const coll = collection(db, "cities"); const q = query(coll, where("state", "==", "CA")); const snapshot = await getCountFromServer(q); console.log('count: ', snapshot.data().count);
Swift
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"), );
Go
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
sum()
集約を使用する
sum()
集計を使用して、特定のクエリに一致する数値の合計を返します。次に例を示します。
ウェブ向けのモジュラー 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);
sum()
集計では、クエリに対するフィルタと制限句が考慮されます。次に例を示します。
ウェブ向けのモジュラー 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);
average()
集約を使用する
特定のクエリに一致する数値の平均を返すには、average()
集計を使用します。次に例を示します。
ウェブ向けのモジュラー 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);
average()
集計では、クエリに対するフィルタと制限句が考慮されます。次に例を示します。
ウェブ向けのモジュラー 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);
クエリ内の複数の集計を計算する
複数の集計を 1 つの集計パイプラインに組み合わせることができます。これにより、必要なインデックスの読み取り数を減らすことができます。クエリに複数の項目の集計が含まれている場合、クエリに複合インデックスが必要になることがあります。その場合、Cloud Firestore はインデックスを提案します。
次の例では、1 つの集計クエリで複数の集計を行います。
ウェブ向けのモジュラー 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);
複数の集計を含むクエリには、各集計のすべてのフィールドを含むドキュメントのみが含まれます。このため、各集計を個別に実行した場合と結果が異なる可能性があります。
集計クエリのセキュリティ ルール
Cloud Firestore セキュリティ ルールの 集約クエリに対する動作は、ドキュメントを返すクエリに対する動作と同様です。つまり、特定のコレクション クエリまたはコレクション グループ クエリをクライアントが実行することがルールで許可されている場合に限り、クライアントはこれらのクエリに対しても 集約を実行できます。詳細については、Cloud Firestore セキュリティ ルールとクエリの相互作用の仕組みをご覧ください。
動作と制限事項
集計クエリを使用する場合は、次の動作と制限事項に注意してください。
リアルタイム リスナーおよびオフライン クエリでは、集約クエリを使用できません。現在、 集約クエリは、直接サーバー レスポンス経由でのみサポートされています。クエリは Cloud Firestore バックエンドによってのみ処理され、ローカル キャッシュとバッファ済みの更新はスキップされます。この動作は、Cloud Firestore トランザクション内で実行されるオペレーションと同じです。
DEADLINE_EXCEEDED
集約が 60 秒以内に解決できない場合は、 エラーが返されます。パフォーマンスは、インデックス構成とデータセット サイズに応じて異なります。60 秒の期限内にオペレーションを完了できない場合、回避策としては、大規模データセット用のカウンタを使用できます。
集計クエリはインデックス エントリから読み取り、インデックス付きフィールドのみを含めます。
集計クエリに
OrderBy
句を追加すると、集計は並べ替える項目が存在するドキュメントに限定されます。sum()
集計とaverage()
集計では、数値以外の値は無視されます。sum()
集計とaverage()
集計では、整数値と浮動小数点数値のみが考慮されます。1 つのクエリで複数の集計を結合する場合、
sum()
とaverage()
は数値以外の値を無視するのに対し、count()
は数値以外の値を含むことに注意してください。異なる項目の集計を組み合わせる場合、計算には、それらのすべての項目を含むドキュメントのみが含まれます。
料金
集計クエリの料金は、クエリによって照合されるインデックス エントリの数に応じて異なります。照合されるエントリが多数ある場合も、少数の読み取りの料金が課金されます。
詳細については、料金に関する情報をご覧ください。