DEV Community

kaede
kaede

Posted on

Elastic Search -- or と filter を組み合わせた検索を実装する

why

https://andor.kb.asia-northeast1.gcp.cloud.es.io:9243/app/dev_tools#/console

複数の key value を持つデータで、
所持金が 100k 以上または、職位が Manager 以上で、
クレジットカードのランクが Gold

この実装をしたい

https://medium.com/eureka-engineering/%E5%9F%BA%E7%A4%8E%E7%B7%A8-elasticsearch%E3%81%AE%E6%A4%9C%E7%B4%A2%E3%82%AF%E3%82%A8%E3%83%AA%E3%82%92%E4%BD%BF%E3%81%84%E3%81%93%E3%81%AA%E3%81%9D%E3%81%86-ace3e18c2174

複数一致と数値範囲は range / gte , これでフィルターできるらしい。

データの作成

POST /user/_doc/1 { "name": "kaede", "cash": "30000", "job_rank": "player", "credit": "green" } 
Enter fullscreen mode Exit fullscreen mode
{ "_index": "user", "_id": "1", "_version": 1, "result": "created", "_shards": { "total": 2, "successful": 2, "failed": 0 }, "_seq_no": 0, "_primary_term": 1 } 
Enter fullscreen mode Exit fullscreen mode

初期データを生成していく。

POST /user/_doc/2 { "name": "tom", "cash": "100000", "job_rank": "manager", "credit": "gold" } 
Enter fullscreen mode Exit fullscreen mode
POST /user/_doc/3 { "name": "suzu", "cash": "200000", "job_rank": "player", "credit": "gold" } 
Enter fullscreen mode Exit fullscreen mode
POST /user/_doc/4 { "name": "yanagi", "cash": "1000000", "job_rank": "manager", "credit": "none" } 
Enter fullscreen mode Exit fullscreen mode

100k あって manager で gold の tom
200k あるが player で gold の suzu
1000k あり manager で none の yanagi

これらのデータも追加し、

tom と suzu だけひっかかるようにする


職位 manager 以上

{ "query": { "bool": { "must": [ { "match": { "job_rank": "manager" } } ] } } } 
Enter fullscreen mode Exit fullscreen mode
 "hits": [ { "_index": "user", "_id": "2", "_score": 0.6931471, "_source": { "name": "tom", "cash": "100000", "job_rank": "manager", "credit": "gold" } }, { "_index": "user", "_id": "4", "_score": 0.6931471, "_source": { "name": "yanagi", "cash": "1000000", "job_rank": "manager", "credit": "none" } } ] 
Enter fullscreen mode Exit fullscreen mode

tom と yanagi だけがひっかかる

ここから gold をフィルターする

GET /user/_search { "query": { "bool": { "must": [ { "match": { "job_rank": "manager" } } ], "filter": [ { "match": { "credit": "gold"}} ] } } } 
Enter fullscreen mode Exit fullscreen mode
 "hits": [ { "_index": "user", "_id": "2", "_score": 0.6931471, "_source": { "name": "tom", "cash": "100000", "job_rank": "manager", "credit": "gold" } } ] 
Enter fullscreen mode Exit fullscreen mode

bool の下には複数条件を置くことができる。

must だけでなく、filter も噛ませることで
クレジットカードが gold も持っている
tom だけに絞り込めた。

ここから、職位が player でも金をもっていれば
ヒットするようにする

GET /user/_search { "query": { "bool": { "should": [ { "match": { "job_rank": "manager" } } ], "filter": [ { "match": { "credit": "gold"}} ] } } } 
Enter fullscreen mode Exit fullscreen mode
 "hits": [ { "_index": "user", "_id": "2", "_score": 0.6931471, "_source": { "name": "tom", "cash": "100000", "job_rank": "manager", "credit": "gold" } }, { "_index": "user", "_id": "3", "_score": 0, "_source": { "name": "suzu", "cash": "200000", "job_rank": "player", "credit": "gold" } } ] 
Enter fullscreen mode Exit fullscreen mode

manager の条件に should を入れて
filter と並列にすると
should の中身が意味をなさなくなってしまう

GET /user/_search { "query": { "bool": { "must": [ { "match": { "job_rank": "manager,player" } }, { "match": { "cash": "100000, 200000" } } ], "filter": [ { "match": { "credit": "gold"}} ] } } } 
Enter fullscreen mode Exit fullscreen mode

なので、must の内部に条件を並べて、
その must を filter と並列に並べれば絞れる。

まとめ

should { A1, A2, }

Top comments (0)