🎇

Firestoreに「COUNT」がやってきた!!(コストとパフォーマンスについて追記)

2022/10/17に公開約2,700字

Google Cloud Next'22で衝撃的な発表がありました!!
とうとうFirestoreにCOUNT機能がきたようです!!🎉🎉早速試してみました。

Firestore as a backend-as-a-service, we've removed the limits for write throughput and concurrent active connections. Now, if your app becomes an overnight success, you can be confident that Firestore will scale smoothly. Additionally, we’re rolling out the COUNT() function in preview next week,

https://cloud.google.com/blog/products/databases/unifying-expanding-optimizing-databases-next22?hl=en

今までListでとってカウントしていたのが不要になる🎉

Firestoreのカウントは至る所で問題がありました。例えばコレクションを丸ごと取ってきてプログラムでカウントする、全文検索エンジンのstatsを使う、RDBを使うなど様々な工夫が求められていました。
しかし念願のCOUNTによってこれも不要に!(どれくらい細かい集計が可能かはこれから検証します)

コード

{
  "name": "playground",
  "version": "1.0.0",
  "main": "index.js",
  "license": "MIT",
  "devDependencies": {
    "typescript": "^4.8.4"
  },
  "dependencies": {
    "firebase": "^9.12.1"
  }
}

倍数に応じてステータスを振った100個のドキュメントを適当に作ります。(2の倍数ならactive、3の倍数ならdelete)
そしてこれ「getCountFromServer」を使ってカウントしてみます!!

import { initializeApp } from 'firebase/app';
import {
  addDoc,
  collection, getCountFromServer, initializeFirestore,
  query,
  where
} from 'firebase/firestore';

const app = initializeApp({ projectId: 'プロジェクト' });
const firestore = initializeFirestore(app, {});

(async () => {
  const collectionRef = collection(firestore, 'Test');

  // Testコレクションの全件カウント
  const totalCount = await getCountFromServer(query(collectionRef));
  // Testコレクションの statusフィールドが「active」なドキュメントをカウント
  const activeCount = await getCountFromServer(query(collectionRef, where('status', '==', 'active')));
  // Testコレクションの statusフィールドが「delete」なドキュメントをカウント
  const deleteCount = await getCountFromServer(query(collectionRef, where('status', '==', 'delete')));

  console.log('totalCount', totalCount.data()); // -> {count: "100"}
  console.log('activeCount', activeCount.data()); // -> {count: "50"}
  console.log('deleteCount', deleteCount.data()); // -> {count: "10"}
})();

結果

おおーー!!クエリに応じてちゃんととれてますね!!

totalCount { count: 100 } // 全数
activeCount { count: 50 } // 2の倍数
deleteCount { count: 17 } // 3の倍数

引数とか実装とか

引数は普通にQueryを取ります。AggregateQuerySnapshotを返却しますが、現時点ではヒットしたドキュメント数の count フィールドだけを返すようです。

protoファイル的には、aggregationsを複数でわたすようになっているので、いつかはCount以外の集計もできるようになったりするんでしょうか(期待)
https://github.com/googleapis/nodejs-firestore/blob/0651c6aadaf35368cc22050404288b1cff133d70/dev/src/reference.ts#L3031-L3053

コストってどうなったの?(追記)

公式ドキュメントにも「最終カウントのみがダウンロードされる=1Readとしてカウントされる」と書いてあるようです
1500ドキュメント=1Readとしてカウントされるようです
こちらで追記しました
https://zenn.dev/mashi/articles/ddf4ee155f50a5#コストに関して

Discussion

ログインするとコメントできます