1:n のドキュメントの
検索で試行錯誤した話
@kaiba
@kaiba
鰓(エラ)
サーチ!
スティック
Esの基礎から実践まで学べる本! 500円
やるぞ!
22inc の Stamps の課題
Stampsの課題
「Kaibaステーキ渋谷店に3回来た人」は1:n
3/1 来店
3/8 来店
3/15 来店
回数の検索はSQLは苦手!
group by して sum して order…
見なくてもわかる遅いやつやん!
好きなだけ条件を
足せる!
User : Checkins = 1: n
どんな設計にする?
ユーザを
index?
店舗を
index?
普通に Aggregation でいけるっしょ期
渋谷店に�3回きた人
20代
+
来店回数を保持すればいいっしょ期
{
"user": {
"id": "6789",
"gender": "man",
"checkins": [
{ "shop_id": "1", count: 3 },
{ "shop_id": "3", count: 1 },
{ "shop_id": "5", count: 1 },
{ "shop_id": "8", count: 1 },
・・・
来店するほど�ドキュメントが�でかくなるよ!
非正規化!
Esらしいアプローチ!
ケースによってはあり
2回クエリ発行期
5千兆人来店していたら…
Join datatype期
Esは非正規化!�と言ったな?
あれは嘘じゃ。
join datatypeはRDBのように使うべきではありません。
Elasticsearchでは非正規化してドキュメントを作ることで
高いパフォーマンスが得られています。
join datatypeが意味を成すのは1つのエンティティに対して
大量のデータが含まれるケースです。
例えば製品と製品の注文です。
この場合、製品を親、注文を子としてドキュメントに
することは適しています。
気になるパフォーマンス
{
"user": {
...
},
"checkin": {
...
},
"my_join_field": {
"name": "user or checkin"
}
}
userかcheckin、どちらかが入ります。
自分がuserなのか、checkinなのかを指定します。
Esのmapping設定であらかじめ親、子を定義してあります。
クエリの例: 店舗1に3回以上来たUserを探す
{
"query": {
"has_child": {
"type": "checkin",
"query": {
"term": {
"checkin.shop_id": 1
}
},
"min_children": 3
}
}}
すげー
よみやすい!
queryがかけるので
最終来店からn日経ったとか複雑な条件もいける
Join datatypeで何が実現できたか
まとめ
ありがとうございました!