見出し画像

AIエンジニアが一ヶ月でアプリ開発11:データベースの設計

こんにちは、りぼっちです。

今回は データベース の設計をしていきたいと思います。

RDB か NoSQL か?

今までの私が設計したアーキテクチャは、ほぼ全て MySQL によるものでした。補助として Memcached や Redis を使うことはあっても、NoSQLをメインで使ったことはありません。

今回のシステムでも Cloud Function経由で GCP の Cloud SQL を使うという選択肢はあるのですが、せっかくの機会ですし、もともと「 Firestore めちゃめちゃ良いよ」って聞いているので Firestore で作ってみたいと思います。

本当に、それだけの理由ですが、仮にちゃんと設計するとなると、今回のデータ構造は自分だけが使うことができるタスクアプリです。いくつもの登場人物が出てきて、複雑に構成したりすることもありませんし、トランザクションで強い整合性が必要なサービスでも無いので、やっぱり NoSQLが向いている気がします。(使ったことないけどw)

Firestoreについて

Firestore は、ドキュメント指向型の NoSQLデータベースです。しかし、ただの NoSQLというよりは非常に高機能になっており、裏側は超高性能DBのGoogle Spanner で構成されています。
Firestore は全カラムにインデックスを構成してくれるので、インデックスが効いていないクエリを発行する心配もないです(複数のカラム条件で検索する場合は別で対応が必要)。
また、Firestore 特有の subCollection という機能もあり、1:Nの関係を柔軟に表現することができます。

使ってみるのが、めちゃめちゃ楽しみです!

アプリの設計思想

今回のアプリは、基本的に TO-DO アプリなので簡単なんですが、そこにプロジェクトという概念が入ります。基本的にプロジェクトは Firestore の subCollection を利用して以下のような構成が良いと思うのですが、TO-DO (task) はどうでしょう。

/user/${user_id}/project/${project_id}

user: {
    {
        id: "abcd0123",
        name: "taro",
        created_at: "2020-09-09 00:00:00",
        project: [
            id: "aaa000",
            title: "ProjectA",
            created_at: "2020-09-09 00:00:00",
            updated_at: "2020-09-09 00:00:00",
        ],
    },
}

project の下に、taskという形で入れても良いんですが、懸念がいくつかあります。一つは、プロジェクト間を変更することができる。これは少々やっかいですね。あとは終了したタスクを、いつまでプロジェクトの中に溜めておくのかというのも気になります。

終了ログを表示するときに、いろいろな project の task を見に行くのは面倒です。(簡単にできるらしいですが、なんだか気持ち悪い)

そこで見つけたのが ReferenceType です。

いったん user/${user_id}/task/${task_id} というものをユーザ以下のsubCollectionとして作っておいて、project 内では こちらの taskごとのリファレンスを所持するというのは、どうでしょう。
これをしても task がプロジェクト間を移動したときは、リファレンスを移動させる必要がありますが、とりあえずログを表示するときや task 自信を更新するときは project 情報が必要なくなるので便利(?)なんじゃないかと思いました。

やっぱりRDBの名残が捨てられないのでしょうか?素直に project 配下に subCollection を作ったほうが良いのでしょうか?誰か教えてくださーい。

ってことで、今のところ以下のような構造で作ろうと思っています。

user: [
    {
        id: "abcd0123",
        name: "taro",
        created_at: "2020-09-09 00:00:00",
        project: [
            id: "aaa000",
            title: "ProjectA",
            task: [
                "/user/abcd0123/task/tasktask",
            ],
            created_at: "2020-09-09 00:00:00",
            updated_at: "2020-09-09 00:00:00",
        ],
        task: [
            {
                id: "tasktask",
                title: "がんばる",
                is_done: False,
                created_at:  "2020-09-09 00:00:00",
                updated_at:  "2020-09-09 00:00:00",
            }
        ]
    }
]

う〜ん。タスクからプロジェクトIDを引けるようにする必要あるかな?

いったん、これで開発してみて運用が厳しそうなら構成を変えてみたりしようと思います。

最後に

本来は、RDBとNoSQLを適材適所に使えるようになるべきなんですが、いかんせん NoSQLの運用経験が浅く、今回せっかくならチャレンジしてみたいと思っております。

何か、ツッコミがあれば優しいコメントをいただけると幸いです。

次は再度実装を再開しようと思います。



この記事が気に入ったらサポートをしてみませんか?