データモデリングとスキーマ管理
(これは「week-of-datomic」二日目の記事です)
一般的なリレーショナルデータベース(以下 RDBMS)はデータ定義言語(DML)とデータ操作言語(DDL)という二つの異なる文法で操作するのですが、Datomic の世界ではデータとデータ構造(以下 schema)を区別しておらず、すべてデータとして扱います。もちろんトランザクションもデータですのでビジネスドメインのメタデータを追加したり、データの変更が発生した当時のトランザクションメタデータも検索できます。
例としてはデフォルトで以下のような問い合わせができます
● この項目はいつ変更されたの?
● この項目と同じトランザクション内で変更された項目は?
● このトランザクションが完了した瞬間、全データベースの状態は?
● この時点、またはトランザクション以降の変更は?
● もし仮にこの変更が発生した場合、全データベースの状態は?
RDBMS でこれらの問い合わせを対応するためには膨大ないコストがかかりますが、Datomic の世界ではデフォルトで使えるような機能ばかりです。そんな便利な Datomic ですが、本日は schema について手を動かしながら勉強したいと思います。
EDN
Datomic 内の schema はすべて EDN というデータ構造で記述されます。RDBMS ではテーブル単位でデータの構造を管理しますが Datomic はアトリビュート単位(RDBMS でいう項目)で管理しており、密に関係性を持っているアトリビュートを同じネームスペースで論理的にまとめます。ここ note.com を例とすると、仮にユーザーの情報を格納するために :user/id と :user/nickname という二つのプロパティを定義して使います。
[{:db/ident :user/id, :db/valueType :db.type/string, :db/cardinality :db.cardinality/one, :db/unique :db.unique/identity}
{:db/ident :user/nickname, :db/valueType :db.type/string, :db/cardinality :db.cardinality/one}]
このようなデーター構造を書き込むことによって schema を設定します。
keyword
:foo/bar
vector
[:item :item]
map
{:key :value}
名前と名前空間
EDN ではよく「:foo.bar/baz」みたいな記号をよく見かけますが、これはキーワードといって名前を表現するための記号です。例えばここでは「baz」が名前ですが、名前があれば名前衝突が発生する可能性があります、そこで名前を区別するための「foo.bar」のような名前空間が存在します。
例としては例えば「nickname」という名前がありますが、「:github.com/nickname」と「note.com/nickname」では意味合いも制限も違うと思います。
:db/ident
RDBMS で言う項目名。名前の衝突を回避するために名前空間を使って区切ることが多い。
:db/valueType
Datomic とはいえ下には JVM が動いているので最適化するためにもプリミティブな型情報が必要です。よく使うものは揃っていますが、現時点で対応しているデータタイプのリストが必要な場合はこちらです。
:db/cardinality
リレーショナルデータモデルを使う場合、データの関係性(リレーション)を考えながらテーブル構造を設計するのですが。
1 対 1 の関係
例:一つのユーザーIDに対して必ず一つのニックネームが付いている
1 対多の関係
例:一つのユーザーIDに対して複数のリアクションを設定出来る
多対多の関係
例:一つのユーザーIDは複数アイテムを購入できて、一つのアイテムは複数のユーザーに販売出来る
このような関係を「:db.cardinality/one」、「:db.cardinality/many」で表現します。例えば「1 対 1 の関係」から「1 対多の関係」に変更する場合、RDBMS ではデータ構造を変えるにはあらかじめ精密なプランニングを行い、DDL でデータ構造を変更して、既存のデータをマイグレーションするという多大な開発作業が発生しますが、Datomic の世界では新しい定義を書き込もだけで変更できます。
サンプルコード
今回は公開されている「MusicBrainz」データセットを使って簡単なサービスを作ってみようと思います。この段階では REPL ベースの開発フロー、スキーママイグレーションまで作成したコードを公開しております。
よかったら起動して遊んでみてください。
この記事が気に入ったらサポートをしてみませんか?