新しい Firebase データベースである Cloud Firestore を使用して、コレクションに含まれるアイテムの数をカウントすることは可能ですか?
もしそうなら、どうすればいいでしょうか?
ベストアンサー1
2023年アップデート
Firestoreがサポートするようになりました集計クエリ。
ノードSDK
const collectionRef = db.collection('cities');
const snapshot = await collectionRef.count().get();
console.log(snapshot.data().count);
ウェブ v9 SDK
const coll = collection(db, "cities");
const snapshot = await getCountFromServer(coll);
console.log('count: ', snapshot.data().count);
注目すべき制限- 現在、count()
リアルタイム リスナーとオフライン クエリではクエリを使用できません。(代替案については以下を参照してください)
価格- 価格は、ドキュメントの数ではなく、一致するインデックス エントリの数によって決まります。1 つのインデックス エントリには複数のドキュメントが含まれるため、ドキュメントを個別にカウントするよりも安価になります。
古い回答
多くの質問と同様に、答えは「それは状況によります」です。
フロントエンドで大量のデータを扱うときは、細心の注意が必要です。フロントエンドが遅くなるだけでなく、Firestoreは100万回の読み取りごとに0.60ドルの料金がかかりますあなたが作る。
小規模コレクション(100件未満の文書)
注意して使用してください - フロントエンドのユーザーエクスペリエンスが損なわれる可能性があります
返された配列に対してあまり多くのロジックを実行しない限り、フロントエンドでこれを処理しても問題ありません。
db.collection('...').get().then(snap => {
size = snap.size // will return the collection size
});
中規模コレクション(100~1000件のドキュメント)
注意して使用してください - Firestore の読み取り呼び出しにはコストがかかる可能性があります
これをフロントエンドで処理するのは、ユーザーのシステムの速度を低下させる可能性が大きすぎるため、現実的ではありません。このロジックはサーバー側で処理し、サイズのみを返す必要があります。
この方法の欠点は、Firestore の読み取り (コレクションのサイズに等しい) が引き続き呼び出されるため、長期的には予想よりもコストがかかる可能性があることです。
クラウド機能:
db.collection('...').get().then(snap => {
res.status(200).send({length: snap.size});
});
フロントエンド:
yourHttpClient.post(yourCloudFunctionUrl).toPromise().then(snap => {
size = snap.length // will return the collection size
})
大規模なコレクション(1000以上のドキュメント)
最もスケーラブルなソリューション
フィールド値.increment()
2019年4月現在、Firestoreでは、カウンターの増分を完全にアトミックに、かつ事前のデータを読み込まずに実行できるようになりました。これにより、複数のソースから同時に更新する場合でも正しいカウンター値が得られるようになり (以前はトランザクションを使用して解決されていました)、実行するデータベース読み取りの数も削減されます。
ドキュメントの削除または作成を監視することで、データベース内にあるカウント フィールドに追加したり、カウント フィールドから削除したりできます。
Firestoreのドキュメントをご覧ください -分散カウンターまたは、こちらをご覧くださいデータ集約著者:Jeff Delaney。彼のガイドは AngularFire を使用する人にとって本当に素晴らしいものですが、彼のレッスンは他のフレームワークにも応用できるはずです。
クラウド機能:
export const documentWriteListener = functions.firestore
.document('collection/{documentUid}')
.onWrite((change, context) => {
if (!change.before.exists) {
// New document Created : add one to count
db.doc(docRef).update({ numberOfDocs: FieldValue.increment(1) });
} else if (change.before.exists && change.after.exists) {
// Updating existing document : Do nothing
} else if (!change.after.exists) {
// Deleting document : subtract one from count
db.doc(docRef).update({ numberOfDocs: FieldValue.increment(-1) });
}
return;
});
これで、フロントエンドでこの numberOfDocs フィールドをクエリするだけで、コレクションのサイズを取得できます。