LoginSignup
10
8

More than 5 years have passed since last update.

ElasticSearchで検索のプロになる!07.Analyzeの話

Last updated at Posted at 2016-02-23

検索を実行していると、これ本当に検索結果あってるの??
というのがある。

厳密には結果に対する疑問というより、検索結果と自分の検索ロジックとに違和感があるという漠然とした感覚です。

RDMSでは実行計画というのがあって、クエリが自分の意図した動きをしているかが確認できる。

ElasticSearchでもそんな機能があって、_analyzeを指定するとそんな結果が出る。

curl -XGET 'http://localhost:9200/search/_analyze?pretty' -d '{"size":100,"from":0,"query":{"query_string":{"query":"text-ja-ma:(\"魔法少女まどか☆マギカ\")^100 OR text-ja-2gram:(\"魔法少女まどか☆マギカ\")^10"}}}'

実行結果

  }, {
    "token" : "魔",
    "start_offset" : 69,
    "end_offset" : 70,
    "type" : "<IDEOGRAPHIC>",
    "position" : 11
  }, {
    "token" : "法",
    "start_offset" : 70,
    "end_offset" : 71,
    "type" : "<IDEOGRAPHIC>",
    "position" : 12
  }, {
    "token" : "少",
    "start_offset" : 71,
    "end_offset" : 72,
    "type" : "<IDEOGRAPHIC>",
    "position" : 13
  }, {
    "token" : "女",
    "start_offset" : 72,
    "end_offset" : 73,
    "type" : "<IDEOGRAPHIC>",
    "position" : 14
  }, {
    "token" : "ま",
    "start_offset" : 73,
    "end_offset" : 74,
    "type" : "<HIRAGANA>",
    "position" : 15
  }, {
    "token" : "ど",
    "start_offset" : 74,
    "end_offset" : 75,
    "type" : "<HIRAGANA>",
    "position" : 16
  }, {
    "token" : "か",
    "start_offset" : 75,
    "end_offset" : 76,
    "type" : "<HIRAGANA>",
    "position" : 17
  }, {
    "token" : "マギカ",
    "start_offset" : 77,
    "end_offset" : 80,
    "type" : "<KATAKANA>",
    "position" : 18
  }, {

なんか、Analyzerが正常に効いていない気がする。

どうやらAnalyzerの設定が間違っているのかなと思って、_analyzeに明示的にAnalyzerを指定できるとのことで、今回設定したものを指定してみる。
まずは、形態素

curl -XGET 'http://localhost:9200/search/_analyze?analyzer=ja-ma-analyzer&pretty' -d '{"size":100,"from":0,"query":{"query_string":{"query":"text-ja-ma:(\"魔法少女まどか☆マギカ\")^100 OR text-ja-2gram:(\"魔法少女まどか☆マギカ\")^10"}}}'

これを実行

  }, {
    "token" : "魔法",
    "start_offset" : 108,
    "end_offset" : 110,
    "type" : "word",
    "position" : 22
  }, {
    "token" : "少女",
    "start_offset" : 110,
    "end_offset" : 112,
    "type" : "word",
    "position" : 23
  }, {
    "token" : "まどか",
    "start_offset" : 112,
    "end_offset" : 115,
    "type" : "word",
    "position" : 24
  }, {
    "token" : "マギカ",
    "start_offset" : 116,
    "end_offset" : 119,
    "type" : "word",
    "position" : 25
  }, {

なんとなく、これなら納得の結果。
次にn-GRAM(バイグラム)

curl -XGET 'http://localhost:9200/search/_analyze?analyzer=ja-2gram-analyzer&pretty' -d '{"size":100,"from":0,"query":{"query_string":{"query":"text-ja-ma:(\"魔法少女まどか☆マギカ\")^100 OR text-ja-2gram:(\"魔法少女まどか☆マギカ\")^10"}}}'

実行結果

}, {
    "token" : "魔法",
    "start_offset" : 108,
    "end_offset" : 110,
    "type" : "word",
    "position" : 109
  }, {
    "token" : "法少",
    "start_offset" : 109,
    "end_offset" : 111,
    "type" : "word",
    "position" : 110
  }, {
    "token" : "少女",
    "start_offset" : 110,
    "end_offset" : 112,
    "type" : "word",
    "position" : 111
  }, {
    "token" : "女ま",
    "start_offset" : 111,
    "end_offset" : 113,
    "type" : "word",
    "position" : 112
  }, {
    "token" : "まど",
    "start_offset" : 112,
    "end_offset" : 114,
    "type" : "word",
    "position" : 113
  }, {
    "token" : "どか",
    "start_offset" : 113,
    "end_offset" : 115,
    "type" : "word",
    "position" : 114
  }, {
    "token" : "か☆",
    "start_offset" : 114,
    "end_offset" : 116,
    "type" : "word",
    "position" : 115
  }, {
    "token" : "☆マ",
    "start_offset" : 115,
    "end_offset" : 117,
    "type" : "word",
    "position" : 116
  }, {
    "token" : "マギ",
    "start_offset" : 116,
    "end_offset" : 118,
    "type" : "word",
    "position" : 117
  }, {
    "token" : "ギカ",
    "start_offset" : 117,
    "end_offset" : 119,
    "type" : "word",
    "position" : 118
  }, {
    "token" : "カ\\",
    "start_offset" : 118,
    "end_offset" : 120,
    "type" : "word",
    "position" : 119
  }, {

きっちり、n-Gramの形式になっている、なので、どうやらAnalyzerの設定は正常らしいということが分かります。
となると、
①ダイナミックマッピングが効いていない
②クエリの方法がまずい

のどちらかのきがするので、まずはテンプレートを見直してみる。

①ダイナミックマッピングの確認
以下のリクエストで設定が確認できるので確認してみる。
まずはanalyzerの確認

curl -XGET http://localhost:9200/search/_settings?pretty

結果

{
  "search" : {
    "settings" : {
      "index" : {
        "creation_date" : "1444197536551",
        "analysis" : {
          "filter" : {
            "greek_lowercase_filter" : {
              "type" : "lowercase",
              "language" : "greek"
            }
          },
          "analyzer" : {
            "ja-ma-analyzer" : {
              "filter" : [ "kuromoji_baseform", "greek_lowercase_filter", "cjk_width" ],
              "type" : "custom",
              "tokenizer" : "ja-ma-tokenizer"
            },
            "ja-2gram-analyzer" : {
              "type" : "custom",
              "filter" : [ "greek_lowercase_filter", "cjk_width" ],
              "tokenizer" : "ja-2gram-tokenizer"
            }
          },
          "tokenizer" : {
            "ja-2gram-tokenizer" : {
              "type" : "nGram",
              "min_gram" : "2",
              "max_gram" : "2"
            },
            "ja-ma-tokenizer" : {
              "type" : "kuromoji_tokenizer",
              "mode" : "normal"
            }
          }
        },
        "number_of_shards" : "5",
        "number_of_replicas" : "1",
        "version" : {
          "created" : "1070199"
        },
        "uuid" : "p5NP1VxfRKO2oPhQM1mavg"
      }
    }
  }
}

ちゃんと設定されていることが分かります。
なので、今度はマッピングの確認

curl -XGET http://localhost:9200/search/_mappings?pretty

実行結果

{
  "search" : {
    "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"
          }
        } ],
        "properties" : { }
      },
      "title" : {
        "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"
          }
        } ],
        "properties" : {
          "category" : {
            "type" : "string"
          },
          "sequenceKey" : {
            "type" : "string"
          },
          "text-ja-2gram" : {
            "type" : "string",
            "analyzer" : "ja-2gram-analyzer"
          },
          "text-ja-ma" : {
            "type" : "string",
            "analyzer" : "ja-ma-analyzer"
          },
          "text1" : {
            "type" : "string"
          },
          "text2" : {
            "type" : "string"
          },
          "text3" : {
            "type" : "string"
          },
          "text4" : {
            "type" : "string"
          }
        }
      }
    }
  }
}

きちんと設定されている。
なので、やはりクエリの書き方がまずいのかもしれない。

ということで、次回はクエリに関して色々試してみることにします。

10
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
8