はじめに
こんにちは。@harada_hiです。
今日はPLAID AdventCalendar 2019 16日目として最近社内で戦っていたデータ設計に関して書いています。
NoSQLが流行りデータ設計のあり方は広がりました。RDBが基本だった際は実際の業務Entityを正規化してテーブルを設計していたかと思います。しかし今はその業務Entityをそのままテーブル化することも可能です。またNoSQLだけでなくRDBにおいてもJSONを保持できるように進化し、1カラム1データが原則という世界からは変わっています。
これらはメリットに繋がっている部分もあれば、むしろやりにくくなった点もあると考えています。今回の話は、そうした一種のやりにくさを解消するための手段の紹介です。
課題: どんな形のデータが来るか分からない
プレイドではCX Platform KARTEを提供しています。このKARTEにはWEB上での行動情報がデータとして集まってきます。
この行動情報の詳細はJSONとなっており、各社各様の形式(スキーマ)で送られてきます。つまりタイトルにあるとおり不定形です。
これによって困るのは、この行動情報の詳細を使って後から集計をする場合です。
例えば購入という行動をブランド毎に集計したいとなった際に、
A社のスキーマ
{
brand: "a"
}
B社のスキーマ
{
item: {
brand_label: ["b"]
}
}
という形でkeyも異なれば、値の型も異なるということが考えられます。
もちろんA社、 B社をそれぞれ個別で集計処理を設ければ達成可能ですが、それは今後もスケールしていこうとするSaaSサービスとして明らかなアンチパターンです。
解決策: 集計軸をユーザーに決めてもらう
上の話は送られてくるデータのスキーマが合わせられれば、一番シンプルに解決できるものです。
しかし計測したい行動情報というのは各社各様であり、そこを揃え切ることは非常に難しいです。
では、どうやって集計を汎用化させていくか?
これは集計軸をユーザーに選んでもらうという手段で解消を図っています。
上のJSONのスキーマの例の場合、
以下のような構成のテーブルを作ってしま う形です。
tenant_id | user_id | event | aggregate_schema | aggregate_value | raw_data |
---|---|---|---|---|---|
A | α | 購入 | brand | ["a"] | {brand: a} |
B | β | 購入 | item.brand_label | ["b"] | {item: {brand_label: ["b"]}} |
集計に使うkeyとvalueを型の決まった世界に落とし込むことで、集計をシンプルかすることができます。
これを組み合わせることでスキーマの形が不定のデータが送られてきたとしても柔軟にデータの集計を行うことが可能になります。RDBでいうところの縦持ちテーブルの考え方です。
完璧な手段ではない
これでできます。という雰囲気で上では書いていますが、実際のところ集計軸をユーザーに決めてもらうことで集計幅を柔軟にする対応は極一部でのみしか対応できていません。
データを汎用的にうまく見せるということの取り組みが弱かったこともあり、
- 複数軸での集計の考慮
- ユーザーに設定してもらわなければいけないコスト
- パフォーマンス的な観点
などでまだまだ検討しなければいけない課題があります。特に最後のパフォーマンス部分に関しては悩みがつきません。
おわりに
今回はスキーマのないデータに対してどう戦っているかという話でした。
なかなか正解のない戦いで、よく悩んでいたりします。
似たような悩みを持っている方がいれば是非お話しましょう!