こんにちは。virapture株式会社でCEOしながらラグナロク株式会社でもCKOとして働いている@mogmetです。
一昔前の聖地巡礼したときの写真がgoogleにサジェストされました。あの花はとても名作なので是非みてない人は見てください。
本日はmonoさんが衝撃な機能をツイートしていたので実際に試してみた記事になります。(monoさん素敵な情報ツイートありがとうございますー!!)
というわけで、Firebaseのバージョン10.0.0から集計系の機能が入ってきたので早速紹介します。
Firestoreの count について
いままでFirestoreでcountを取得するためには全件取得するか、count用のフィールドを作って、ドキュメントが作られるたびにインクリメントするみたいな処理を作る必要がありました。
しかし、今回のこの機能を使えばさらっとcountがとれてしまうという素敵な機能になります!!
公式ドキュメントによるとQueryにcountが増えているようです。
https://firebase.google.com/docs/reference/swift/firebasefirestore/api/reference/Classes/Query#/c:objc(cs)FIRQuery(py)count
実装
今回のサンプルは下記リポジトリに置いておきました。
まず初期化します。
import SwiftUI
import Firebase
import FirebaseFirestore
@main
struct FirestoreCountApp: App {
init() {
FirebaseApp.configure()
// emulatorを使わない場合は下記settingsをすべてコメントアウトする
let settings = Firestore.firestore().settings
settings.host = "localhost:8080"
settings.isPersistenceEnabled = false
settings.isSSLEnabled = false
Firestore.firestore().settings = settings
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
実装はこんな感じ。
import SwiftUI
import FirebaseFirestore
struct ContentView: View {
@State var countText: String = "none"
var body: some View {
VStack {
Text(countText)
Button {
Task {
await loadCount()
}
} label: {
Text("Load count")
}
}
.padding()
}
func loadCount() async {
let aggregateSnapshot = try! await Firestore.firestore().collection("users").count.getAggregation(source: .server)
countText = aggregateSnapshot.count.stringValue
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
ここが肝になります。countがニョキッと生えてます。
let aggregateSnapshot = try! await Firestore.firestore()
.collection("users").count.getAggregation(source: .server)
ボタンを押して挙動を確認してみます。
before | after |
---|---|
リードコストは少なくなるのか?
多分 少なくなるというのが結論です。
実際に挙動を試してみたのですが、読み取りが一切カウントされませんでした。(webがまだcountに対応してない?)
(ちなみにぴょんとreadが飛び上がってるのはwebコンソールを開いてデータを確認したため上がってるだけです。)
emulatorもgetDocumentsしたときと結果がかわらなくて本当にリードコストが少なくなってるかは謎です。
一応ドキュメントでは下記の通り説明があります。
A query that counts the documents in the result set of this query.
The AggregateQuery query, when executed, counts the documents in the result set of this Query without actually downloading the documents.
Using the returned query to count the documents is efficient because only the final count, not the documents’ data, is downloaded. The returned query can even count the documents if the result set would be prohibitively large to download entirely (e.g. thousands of documents).
ざっくりいうと実際にダウンロードすることなく結果のカウントだけするから効率的だぜと言ってます。
なのでおそらく1read換算になるのでは・・・・?という判断です。
リアルタイム取得はできる?
結論でいうと 多分まだできない? になります。
理由としてはAggregateQueryにListenerを返すメソッドがないからになります。
ただ、AggregateQuery自体にはqueryを返すものが生えていてそこをたどればaddSnapshotListenerを呼び出すことはできるのですが、挙動的にいつも通りのコレクションの全リードが発生してそうな雰囲気でした。
(snapshotsのなかにデータが入っていた)
今後拡充される可能性はありますが、もう少し様子見な感じです。
(もし誰かやり方わかったら教えて下さい!)
まとめ
countがリードコストもかさまずにコールすることができるようになりました!
集計系は今後も増えそうな雰囲気なのでますますfirestoreが便利になっていくので期待です!
最後に、ワンナイト人狼オンラインというゲームを作ってます!よかったら遊んでね!
他にもCameconやOffcha、問い合わせ対応が簡単にできるCSmart、フリーランスのコミュニティのNextFreelanceといったサービスも作ってるのでよかったら使ってね!
また、チームビルディングや技術顧問、Firebaseの設計やアドバイスといったお話も受け付けてますので御用の方は弊社までお問い合わせください。
ラグナロクでもエンジニアやデザイナーのメンバーを募集しています!!楽しくぶち上げたい人はぜひお話ししましょう!!