概要
検索した時に「部分一致させたいけど、上位に出るのは前方一致してるものがいいなぁ」といった時の対応。
検索文字 | デフォルト | 希望 |
---|---|---|
fa | fate refactor |
fate refactor |
環境
- Ubuntu 14.04
- Elasticsearch 1.5.0
マッピング
fields
を複数設定します。以前はmulti_field
として使われていましたが、1.5系からdeprecatedになるそうです。
これによって「部分一致用」と「前方一致用」の2つのデータを登録できます。
{ "settings": { "analysis": { "analyzer": { "ngram_analyzer": { "tokenizer": "ngram_tokenizer" } }, "tokenizer": { "ngram_tokenizer": { "type": "nGram", "min_gram": 2, "max_gram": 3, "token_chars": [ "letter", "digit" ] } } } }, "mappings": { "internet": { "_all": { "enabled": false }, "dynamic": false, "properties": { "term": { "type": "string", "fields": { "raw": { "type": "string", "index": "not_analyzed" }, "tokenized": { "type": "string", "index": "analyzed", "analyzer": "ngram_analyzer" } } } } } } }
このように各フィールド(term.tokenzed
、term.tokenized
)毎にアナライザを設定します。
データ用意
curl -s -XPOST localhost:9200/test/_bulk -d ' {"index": {"_type": "internet", "_id": "1"}} {"term": "fate"} {"index": {"_type": "internet", "_id": "2"}} {"term": "refactor"} {"index": {"_type": "internet", "_id": "3"}} {"term": "facebook"} '
クエリ
今まで
curl localhost:9200/test/internet/_search?pretty -d ' { "query": { "match": { "term.tokenized": { "query": "fa" } } }, "size": 5, "from": 0 } '
結果
fate refactor facebook
今回
Bool Queryを使います。Multi Match QueryやDis Max Queryでも似たようなことができますが、単純にスコアに加点していく方式ならこちらを使います。
今回は
- 部分一致:match query(ngram)
- 前方一致:prefix query
の2要素でスコアを付けます。
curl localhost:9200/test/internet/_search?pretty -d ' { "query": { "bool": { "should": [ { "match": { "term.tokenized": { "query": "fa" } } }, { "prefix": { "term.raw": { "value": "fa" } } } ] } }, "size": 5, "from": 0 } '
結果
fate facebook refactor
prefix queryによってスコアが加算されたため、順番が変わり要望通りになりました。