DatastoreのERD設計

TemPlat ConsoleではデータベースをDatastore(KVS)とCloudSQL(RDB)から選択出来ます。
ここではDatastore(KVS)を使用した場合のERD設計の進め方を説明します。

Datastore(KVS)の特徴

一般的に、データベースとしてはリレーショナルデータベース(RDB)が一番ポピュラーかと思います。TemPlatでもRDB(CloudSQL)も利用できますが、コスト面も考えるとKVSのDatastoreもお勧めです。

KVSではRDBのようなテーブル間のリレーションが使えないので、ERDを設計する際に考慮が必要です。更新処理に関してはRDBと大きな違いはなく基本1レコードづつ操作するのであまり考慮は必要ありませんが、データを参照する際に注意が必要です。

Datastoreでの関連テーブルの取得方法

RDBでは関連するテーブルのデータを参照する際には、SELECT文にリレーション(join)を使って親テーブルと一緒に子テーブルのレコードも参照できます。ですがDatastoreではそのjoinが使えません。それぞれのテーブルを別々にSELECTする必要があります。この参照のやり方を意識してERDを考えておく必要があります。

以下によく使うパターンを紹介します。

子供が親を知っているパターン

これはRDBでも利用するパターンですが、一番利用するパターンが子テーブル側に親のキーを持つパターンです。こらは親と子が1:nの関係を持つ場合によく使います。

RDBの場合は、この子テーブルが持っている親テーブルのIDを使ってSQLでjoinして同時にデータを取得するなど可能です。Datastoreを使用した場合は、これをAPIのソース上(GoLangのHandler内)で親テーブルと子テーブル両方にSELECTを掛けていきます。

例えば、上記のテーブル構成の例で、OrderテーブルへのKey指定でのGET処理があり、その場合に必ず子テーブルの該当レコードの一覧も返したい場合などが考えられると思います。
その場合は、親のKeyを条件に子テーブルを検索します。そしてそれをレスポンスに配列としてセットして、親の1レコードをあわせてAPIとして返却することができます。

親が子供のID一覧を持っている

2つ目のパターンは親が子テーブルのID一覧を配列としてもつケースです。これはRDBでは関連テーブルを間に持つような、親と子がN:Nになるようなケースなどで利用することが考えられます。

以下の例だとプロジェクトに複数のメンバーが所属するようなケースです。ユーザは複数のプロジェクトに所属できるので、子供が親のIDを持つ1つ前のパターンは使いづらいので、親テーブルの各レコードに子テーブルのIDの配列を持つ形でリレーションを作ります。

この場合は、子供の一覧を取得する場合には、親テーブルが持つ子テーブルの複数のIDを指定して「multiGet」というDatastoreの検索方法を使って、複数IDをまとめて取得することができます。

子テーブルをStructとして持つパターン

ここまではTable間のリレーションの持たせ方を話してきましたが、Datastoreにはもう一つ方法があります。それがstructです。RDBだとあまり馴染みないですが、別のレコードを1カラムとして持つことができるイメージになります。または、一つのカラムにJSON構造のデータ型が使えると思って頂いても良いかと思います。。

上の例では、商品が複数のオプションを持つことができるのをStructの配列で保持しています。Structを配列で持つこともできますし、1件のみ持つこともできます。Structの場合は、親テーブルのレコードの一部であるので、標準のソースコードのままで親の1回のSELECTで、子テーブルの一覧も同時に取得できます。更新するときも同様に親テーブルのレコードの一部としてまとめてINSERTやUPDATEDができます。

注意する点としては、親レコードの一部なので、Structの1レコードのみをINSERTやUPDATEすることはできないというものです。これはシステムの利用者が複数いて、同時に更新する可能性が高いテーブルでは注意が必要です。

親レコードの単位でしか更新できないので、「同時更新ができない」、「排他制御を考慮しないと、他の人の更新を消してしまう」などの課題がでてくることがあります。この辺は別の記事として書きたいと思います。

DatastoreのKeyのIDとNameに関して

Datastoreの各レコードにはテーブル内で一意となる「Key」が必要です。このKeyですが実は2種類のパターンがあります。IDとNameがその2つです。

IDは整数型(number型)で、自動採番も可能なKeyです。特にKeyに意味をもたせる必要がなければ基本このIDを使うのがお勧めです。INSERTする際にIDを未指定にしておけばDatastoreが採番してくれます。また、アプリ側でIDを指定してあげることもできますがあまり使うシーンはないかと思います。

もう一つのNameは文字列型で、こちらは必ずアプリ側で指定してINSERTする必要があります。何か要件的にルールが決まっていて、それをKeyとして利用したい場合に使います。番号体型をコード化しているような場合に使われます。

例えば、「商品コード」や「社員番号」などがあるかと思います。あとは、外部システムで既に採番されているものなどが該当します。

TemPlatのERD作成では、デフォルトでnumber型のIDが使われますが、もちろんNameをKeyに使うことも可能です。以下のように項目名はIDのまま、Typeをstringにするだけです。