wheatandcatの開発ブログ

React Nativeで開発しているペペロミア & memoirの技術系記事を投稿してます

Firestoreを新設計にマイグレーションする

元々Firestoreを使いこなせてない感がすごくあったので、改めて学習し直して新設計にマイグレーションしようとしているので、その辺の実装について記事にしていきます。

まず、現状のFirestoreの設計が以下です。

現状の Firestoreの設計(悪い例)

├──users/:id
├──calendars/:id
├──items/:id
├──itemDetails/:id
└──expoPushTokens/:id

Firestoreの性質を理解してなかったこともありRDBっぽい設計になっていました。 こういう設計にしていると、Firestoreのwhere-inは双方10件までしか取得できないという制限があるため、inを使用したクエリを複数回分けて実行するなど、非常に面倒な実装をすることになります。

また、こういう設計にせずともCollectionGroupを使用することで、同じようなデータは取得できるので上記のような設計にするメリットは、ほぼ無いと思います。

qiita.com

ということで、以下のようなにFirestoreの構造を設計し直しました。

Firestoreの新設計

/version/1/users/:id
    ├──expoPushTokens/:id
    └──calendars/:date
        └──items/:id
            └──itemDetails/:id

以下、新設計の説明

versionを設定することで今後、設計変更が起きた時にバージョンを上げて対応できるように修正

version/1

データは全てusersに紐づくため先頭に設計

users/:id
    ├──expoPushTokens/:id
    └──calendars/:date

予定のデータはカレンダーに紐づくように修正してcalendars(日付情報)→items(メインの予定情報)→itemDetails(各予定の詳細情報)としました。 またcalendarsのドキュメントのIDはdate(日付)で設定する設計に変更(1日1スケジュールの関係なので)

calendars/:date
     └──items/:id
         └──itemDetails/:id

こちらの設計にすることでアプリ内で自身のユーザーのカレンダーの情報が欲しい時は以下にアクセスすれば取得できます。

version/1/users/:id/calendars

また、2020年1月1日の予定を取得するには以下

version/1/users/:id/calendars/2020-01-01/items

2020年1月1日の予定の詳細を取得するには以下になります。

version/1/users/:id/calendars/2020-01-01/items/:id/itemDetails/:id

と、このようにユーザー起点でデータを取得するのが非常にシンプルになりました。

また、ユーザー間を超えてデータを取得したい場合は、CollectionGroupを使用して以下のように取得します。

例)バッチ処理でPush通知を送るため、全ユーザーで2020年1月1日の予定を取得する必要がある

CollectionGroup("calendars").Where("date" "==" "2020-01-01")

これで各usersの配下にあるcalendarsを1まとめにして検索することができます。

と、こんな感じで使用することができ、Firestoreらしい設計に変更できたかなと思います。

既存データのマイグレーションは以下のスクリプトで実装しています。

github.com

また、新設計に合わせてbackendの方も書き換え中なので、その辺が実装が終わったら、また記事に使用と思います