Elasticsearchの親子関係のまとめ
概要
現在作成しているシステムにおいて、DBはDynamoDBを採用している。
DynamoDBのLSI, GSIの取り回しだけでは検索に限界があるので、
DynamoDBStream経由でElasticsearchにインデックスして、
Elasticesearchに検索を任せている。
Elasticsearchのドキュメントにリレーションを持たせないことがあるが、
よく内容を忘れるので備忘のためにこちらに記載しておきます。
シナリオ
- Company
- Employee
の2つのエティティがある。 全部kibanaで試すのを想定
Comapnyが親、Employeeが子
mappingsの定義
PUT /index/ { "mappings": { "properties": { "company": { "properties": { "name": { "type": "keyword" }, "years": { "type": "integer" } } }, "employee": { "properties": { "name": { "type": "keyword" }, "age": { "type": "integer" } } }, "company_employee_relation": { "type": "join", "relations": { "company": "employee" } } } } }
ポイント
- company_employee_relationは適当な名称でOK
- relationsの中は「 {親}:{子} 」にする。あとでdocを登録するときに使用する
データの登録
PUT /index/_bulk {"index": { "_id": "Company:001"}} { "company": {"name": "株式会社ソックス", "years": 80}, "company_employee_relation": "company"} {"index": { "_id": "Company:002"}} { "company": {"name": "キャップ工業株式会社", "years": 120}, "company_employee_relation": "company"} {"index": { "_id": "Company:003"}} { "company": {"name": "株式会社フーディー", "years": 30}, "company_employee_relation": "company"} {"index": { "_id": "Employee:001", "routing": "Company:001"}} { "employee": {"name": "武石徹", "age": 32}, "company_employee_relation": {"name": "employee", "parent": "Company:001"}} {"index": { "_id": "Employee:002", "routing": "Company:001"}} { "employee": {"name": "宮市武", "age": 30}, "company_employee_relation": {"name": "employee", "parent": "Company:001"}} {"index": { "_id": "Employee:003", "routing": "Company:003"}} { "employee": {"name": "相田宗介", "age": 31}, "company_employee_relation": {"name": "employee", "parent": "Company:003"}} {"index": { "_id": "Employee:004", "routing": "Company:002"}} { "employee": {"name": "田中仁", "age": 31}, "company_employee_relation": {"name": "employee", "parent": "Company:002"}}
ポイント
- 親を登録する時に以下を指定
- relation名(ここでいうと"company_employee_relation")
- 親の種類(ここでいうと"company")
- 子を入れる時に以下を指定
- relation名(ここでいうと"company_employee_relation")
- nameは子の種類(ここでいうと"employee")
- parentのindexを指定(ここでいうと"Company:00X")を指定する
- indexのroutingで親のindexを指定(親と同一shardsに入れるため)
クエリの例
以下のような感じで、{クエリ}という親/子をもつindexを検索という感じのクエリが可能
GET /index/_search { "query": { "has_parent": { "parent_type": "company", "query": { "wildcard": { "company.name": { "value": "株式会社*" } } } } } }
GET /index/_search { "query": { "has_child": { "type": "employee", "query": { "range": { "employee.age": { "gte": 31, "lte": 32 } } }, "inner_hits": {} } } }
所感
顧客のレガシーシステムをマイクロサービスな構成にマイグレーションする案件を受けることが多い。
お客様の頭はRDBMSな感じになっていることも多くて、そうなってくると結構リレーションの多い検索要件があったりする。
DynamoDBファーストチョイスで考えていると対応できないことも多いけど、
Elasticsearchを使うと結構器用に扱えるのいいなと思いました。
(あんまり日本語の字句解析とかElasticsearchっぽいことはあまりできていないけど...)