ElasticSearchで検索のプロになる！06.検索精度上げのための設定

前回ではtemplateを使ってインデックスに対して特定のフィールド名に対してMappingする方法を試してみました。

最初はこれでも満足なのですが
ある程度動いてくると、検索の精度に関して色々チューニングしたくなってくる。
それについて記載していきます。

まずはよくあるアルファベットの大文字、小文字

テンプレートを弄って設定を変更します。
まずはオリジナル。

```
{
        "template":"search*",
        "settings":{
                "analysis":{
                        "analyzer":{
                                "ja-ma-analyzer":{
                                        "type":"custom",
                                        "tokenizer":"ja-ma-tokenizer"
                                },
                                "ja-2gram-analyzer":{
                                        "type":"custom",
                                        "tokenizer":"ja-2gram-tokenizer"
                                }
                        },
                        "tokenizer":{
                                "ja-ma-tokenizer":{
                                        "type":"kuromoji_tokenizer",
                                        "mode":"normal"
                                },
                                "ja-2gram-tokenizer":{
                                        "type":"nGram",
                                        "min_gram":"2",
                                        "max_gram":"2"
                                }
                        }
                }
        },
        "mappings":{
                "_default_":{
                        "dynamic_templates":[
                        {
                                "search_text_for_ma":{
                                        "match":"text-ja-ma",
                                        "mapping":{
                                                "type":"string",
                                                "store":"no",
                                                "analyzer":"ja-ma-analyzer"
                                        }
                                }
                        },
                        {
                                "search_text_for_2gram":{
                                        "match":"text-ja-2gram",
                                        "mapping":{
                                                "type":"string",
                                                "store":"no",
                                                "analyzer":"ja-2gram-analyzer"
                                        }
                                }
                        }
                        ]
                }
        }
}
}
```

変更後

```
{
        "template":"search*",
        "settings":{
                "analysis":{
                        "filter":{
                                "greek_lowercase_filter" : {type: "lowercase", language: "greek"}
                        },
                        "analyzer":{
                                "ja-ma-analyzer":{
                                        "type":"custom",
                                        "tokenizer":"ja-ma-tokenizer",
                                        "filter": ["kuromoji_baseform", "greek_lowercase_filter", "cjk_width"]
                                },
                                "ja-2gram-analyzer":{
                                        "type":"custom",
                                        "tokenizer":"ja-2gram-tokenizer"
                                }
                        },
                        "tokenizer":{
                                "ja-ma-tokenizer":{
                                        "type":"kuromoji_tokenizer",
                                        "mode":"normal"
                                },
                                "ja-2gram-tokenizer":{
                                        "type":"nGram",
                                        "min_gram":"2",
                                        "max_gram":"2"
                                }
                        }
                }
        },
        "mappings":{
                "_default_":{
                        "dynamic_templates":[
                        {
                                "search_text_for_ma":{
                                        "match":"text-ja-ma",
                                        "mapping":{
                                                "type":"string",
                                                "store":"no",
                                                "analyzer":"ja-ma-analyzer"
                                        }
                                }
                        },
                        {
                                "search_text_for_2gram":{
                                        "match":"text-ja-2gram",
                                        "mapping":{
                                                "type":"string",
                                                "store":"no",
                                                "analyzer":"ja-2gram-analyzer"
                                        }
                                }
                        }
                        ]
                }
        }
}
}
```

フィルターの設定が追加されました。
各フィルターの設定内容に関しては後述するとして、試してみる。

まずは、登録してあるテンプレートを削除

```
curl -XDELETE http://localhost:9200/_template/main_template
```

んで登録

```
curl -XPUT http://localhost:9200/_template/main_template -d @search_template.json
```

テンプレート見てみる。

```
curl -XGET http://localhost:9200/_template/?pretty
```

```
{
  "main_template" : {
    "order" : 0,
    "template" : "search*",
    "settings" : {
      "index.analysis.filter.greek_lowercase_filter.type" : "lowercase",
      "index.analysis.tokenizer.ja-2gram-tokenizer.max_gram" : "2",
      "index.analysis.analyzer.ja-2gram-analyzer.tokenizer" : "ja-2gram-tokenizer",
      "index.analysis.analyzer.ja-2gram-analyzer.type" : "custom",
      "index.analysis.tokenizer.ja-ma-tokenizer.type" : "kuromoji_tokenizer",
      "index.analysis.tokenizer.ja-2gram-tokenizer.type" : "nGram",
      "index.analysis.analyzer.ja-ma-analyzer.filter.1" : "greek_lowercase_filter",
      "index.analysis.analyzer.ja-ma-analyzer.filter.2" : "cjk_width",
      "index.analysis.tokenizer.ja-ma-tokenizer.mode" : "normal",
      "index.analysis.analyzer.ja-ma-analyzer.filter.0" : "kuromoji_baseform",
      "index.analysis.analyzer.ja-2gram-analyzer.filter.0" : "greek_lowercase_filter",
      "index.analysis.analyzer.ja-ma-analyzer.tokenizer" : "ja-ma-tokenizer",
      "index.analysis.analyzer.ja-2gram-analyzer.filter.1" : "cjk_width",
      "index.analysis.filter.greek_lowercase_filter.language" : "greek",
      "index.analysis.analyzer.ja-ma-analyzer.type" : "custom",
      "index.analysis.tokenizer.ja-2gram-tokenizer.min_gram" : "2"
    },
    "mappings" : {
      "_default_" : {
        "dynamic_templates" : [ {
          "search_text_for_ma" : {
            "mapping" : {
              "analyzer" : "ja-ma-analyzer",
              "store" : "no",
              "type" : "string"
            },
            "match" : "text-ja-ma"
          }
        }, {
          "search_text_for_2gram" : {
            "mapping" : {
              "analyzer" : "ja-2gram-analyzer",
              "store" : "no",
              "type" : "string"
            },
            "match" : "text-ja-2gram"
          }
        } ]
      }
    },
    "aliases" : { }
  }
}
```

しっかり設定されているのが分かる。

さて、ここで、設定したフィルターの説明。

```
"greek_lowercase_filter" : {type: "lowercase", language: "greek"}
```

これは登録時、検索時に大文字は全て小文字に変換するもの。
これにより、大文字、小文字に関係なく検索できるようになる。

```
cjk_width
```

あとは↑これ。全角英数字を半角に直し，半角カタカナを全角に直すなど，漢字圏の文字の全半角を整えることでマッチングをしやすくします。

このあたりかも。

あとはDefultでは10件取得のものをQueryのJsonにsizeとfromを追加してPager対応しておいた。

次はこうして設定した内容が実際にどうElasticSearchで解析されるのか。
その辺を記載したいと思います。