5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

FirebaseAdvent Calendar 2023

Day 5

[Firebase] Firestoreの集約クエリ (count, sum, average) について

Last updated at Posted at 2023-12-04

Firestoreの集約クエリ (aggregation queries) を使用すると、複数のドキュメントの統計的な操作が簡単に行えます。
具体的には以下の3種類のクエリがあります。

  • count
  • sum
  • average

公式ドキュメントではSwiftでのFirestoreのcountクエリの使い方についての説明がありましたが、sumやaverageに関する具体的なSwiftでの実装例は見つかりませんでした。そこで、この記事ではこれら3つのクエリ(count、sum、average)をSwiftでどのように使うかについて解説していきたいと思います。

また、料金的なメリットもありますので、それについても解説していきます。

実装方法

説明するにあたって、このような構造のコレクションがあるとします。

- users # (Collection)
    - user1 # (Document ID)
        - name: "Mike"
        - age: 10
    - user2
        - name: "Takeshi"
        - age: 21
    - user3
        - name: "Taro"
        - age: 20

count

countクエリではコレクションまたはクエリ内のドキュメントの数を取得することができます。
以下の例は20歳以上のユーザー数を取得するコードです。

let count = try await Firestore.firestore()
    .collection("users")
    .whereField("age", isGreaterThanOrEqualTo: 20)
    .count
    .getAggregation(source: .server)
    .count
    .intValue
print(count) // 2

sum

sumクエリでは、コレクションまたはクエリ内の特定のfieldの合計値を取得することができます。
以下の例は全てのユーザーの歳を足して、その結果を取得するコードになっています。

let sum = try await Firestore.firestore()
    .collection("posts")
    .aggregate([.sum("age")])
    .getAggregation(source: .server)
    .get(.sum("age")) as? Int
print(sum) // Optional(51)

average

averageクエリでは、コレクションまたはクエリ内の特定のfieldの平均値を取得することができます。
以下の例はユーザーの平均年齢を取得するコードになっています。

let averageAge = try await Firestore.firestore()
    .collection("posts")
    .aggregate([.average("age")])
    .getAggregation(source: .server)
    .get(.average("age")) as? Double
print(averageAge) // Optional(17)

また、複数のfieldに対して集約クエリを実行することも可能です。

let aggregateQuerySnapshot = try await Firestore.firestore()
    .collection("posts")
    .aggregate([.average("age"), .sum("age")])
    .getAggregation(source: .server)

let sumAge = aggregateQuerySnapshot.get(.sum("age")) as? Int
let averageAge = aggregateQuerySnapshot.get(.average("age")) as? Double

print(sumAge) // Optional(51)
print(averageAge) // Optional(17)

料金的なメリット

通常、Firestoreは読み取り・書き込み・削除を行うドキュメントのに対して課金されます。
なので、1000個のドキュメントを読み取ったら1000回分の課金がなされます。

一方、集約クエリの場合は1000個のドキュメントにつき1回のドキュメント読み取り料金が発生します。
これにより、大幅な費用の削減を行うことができます。

しかし、集約する対象のドキュメントが1件であっても1回のドキュメント読み取り量が発生しますので注意してください。

参考

5
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?