質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.22%

ElasticSearch(sudachi)でクエリがヒットしない

解決済

回答 1

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 1,213

ikasoumen

score 107

社内向けにElasticSearch(全文検索)の検証を行っています。
検証中に、理解できない事象に遭遇したため、ElastiSearchについて知見を持っている方のアドバイスを頂きたいと考えています。

事象

テキストをインデックスし、インデックスした「同一のテキスト」でmatch_phraseした際に、マッチを得られない。
「同一のテキスト」でクエリしているため、マッチが得られる想定。

環境

以下の環境で事象が再現している。

  • ElasticSearch 6.8.1 & Kibana(共にWindows10上にホスト)
  • sudachi(構文解析器)
  • sudachi full版 辞書(small版辞書では事象は再現しない。同様にkuromojiでも事象は再現しない。)
  • kibana discover & kibana dev tool

再現手順(kibana dev toolを想定)

1. elastic sudachi導入

導入手順は、後述の環境構築手順を参考。
辞書は、full版を導入する。

2. マッピング設定

プレーンなsudachi analyzerとフィールドを設定する。

PUT mytestindex
{
  "settings": {
    "number_of_shards": 1,
    "number_of_replicas": 0,
    "index.query.default_field": [
      "sudachi_field"
    ],
    "analysis": {
      "analyzer": {
        "default": {
          "tokenizer": "sudachi_tokenizer",
          "type": "custom"
        },
        //kuromojiで検証する場合
        "kuromoji_analyzer": {
          "type": "custom",
          "tokenizer": "kuromoji_tokenizer"
        }
      },
      "tokenizer": {
        //full版辞書では、mode: normal,search,extended共にマッチが得られない。small版辞書では、満足する結果が得られている。
        "sudachi_tokenizer": {
          "type": "sudachi_tokenizer",
          "mode": "search",
          "resources_path": "sudachi_tokenizer" //デフォルトで、<elasticsearch_config>/sudachi_tokenizer/system_core.dic を参照する
        }
      }
    }
  },
  "mappings": {
    "_doc": {
      "properties": {
        "sudachi_field": {
          "type": "text",
          "analyzer": "default",
          "search_analyzer": "default",
          "store": true,
          "fielddata": true,
          "fields": {
            "keyword": {
              "type": "keyword",
              "ignore_above": 256
            }
          }
        }
      }
    }
  }
}

2. インデックス

テストケースを登録する。

POST _doc/_bulk
{ "index" : { "_index" : "mytestindex", "_type": "_doc", "_id" : "1" } }
{ "sudachi_field": "十一代目 市川海老蔵"}
{ "index" : { "_index" : "mytestindex", "_type": "_doc", "_id" : "2" } }
{ "sudachi_field": "十一代目市川海老蔵"}
{ "index" : { "_index" : "mytestindex", "_type": "_doc", "_id" : "3" } }
{ "sudachi_field": "11代目 市川海老蔵"}
{ "index" : { "_index" : "mytestindex", "_type": "_doc", "_id" : "4" } }
{ "sudachi_field": "11代目市川海老蔵"}

3. クエリの発行

クエリを発行する。

GET mytestindex/_search
{
  "query": {
    "bool": {
      "must": [],
      "filter": [
        {
          "bool": {
            "filter": [
              {
                "bool": {
                  "should": [
                    //=================================================
                    //ヒットしないケース
                    //=================================================
                    {
                      "match_phrase": {
                        "sudachi_field": "十一代目市川海老蔵"
                      }
                    },
                    {
                      "match_phrase": {
                        "sudachi_field": "十一代目 市川海老蔵"
                      }
                    },
                    {
                      "match_phrase": {
                        "sudachi_field": "11代目市川海老蔵"
                      }
                    },
                    {
                      "match_phrase": {
                        "sudachi_field": "11代目 市川海老蔵"
                      }
                    },
                    {
                      "match_phrase": {
                        "sudachi_field": "11代目市川"
                      }
                    },
                    {
                      "match_phrase": {
                        "sudachi_field": "十一代目 市川"
                      }
                    },
                    {
                      "match_phrase": {
                        "sudachi_field": "十一代目市川"
                      }
                    },
                    {
                      "match_phrase": {
                        "sudachi_field": "11代目 市川"
                      }
                    }
                    //=================================================
                    //ヒットするケース
                    //=================================================
                    //,{
                    //  "match_phrase": {
                    //    "sudachi_field": "十一代目"
                    //  }
                    //}
                    //,{
                    //  "match_phrase": {
                    //    "sudachi_field": "11代目"
                    //  }
                    //}
                    //,{
                    //  "match_phrase": {
                    //    "sudachi_field": "市川"
                    //  }
                    //}
                    //,{
                    //  "match_phrase": {
                    //    "sudachi_field": "海老蔵"
                    //  }
                    //}
                    //,{
                    //  "match_phrase": {
                    //    "sudachi_field": "市川海老蔵"
                    //  }
                    //}
                    //,{
                    //  "match_phrase": {
                    //    "sudachi_field": "市川 海老蔵"
                    //  }
                    //}
                  ],
                  "minimum_should_match": 1
                }
              }
            ]
          }
        }
      ],
      "should": [],
      "must_not": []
    }
  }
}

4. 結果確認

{
  "took" : 1,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : 0,
    "max_score" : null,
    "hits" : [ ]
  }
}

5. 検証

  • [十一代目 市川]等で検索した場合、解析結果は[十一代目 市川海老蔵]となっていることから、[十一代目 市川]にマッチしないのは納得できる
  • [十一代目 市川海老蔵]等で検索した場合、同一の解析結果が得られると想定しているため、マッチしないのは納得できない
  • sudachiのsmall辞書で解析した場合はフルネーム単位で解析されず、苗字・名前単位で解析されるためマッチした
  • kuromojiで解析した場合はフルネーム単位で解析されず、苗字・名前単位で解析されるためマッチした

GET mytestindex/_analyze

{
  "tokens" : [
    {
      "token" : "十一",
      "start_offset" : 0,
      "end_offset" : 2,
      "type" : "word",
      "position" : 0
    },
    {
      "token" : "代目",
      "start_offset" : 2,
      "end_offset" : 4,
      "type" : "word",
      "position" : 1,
      "positionLength" : 2
    },
    {
      "token" : "代",
      "start_offset" : 2,
      "end_offset" : 3,
      "type" : "word",
      "position" : 1
    },
    {
      "token" : "目",
      "start_offset" : 3,
      "end_offset" : 4,
      "type" : "word",
      "position" : 2
    },
    {
      "token" : "市川海老蔵",
      "start_offset" : 4,
      "end_offset" : 9,
      "type" : "word",
      "position" : 3,
      "positionLength" : 2
    },
    {
      "token" : "市川",
      "start_offset" : 4,
      "end_offset" : 6,
      "type" : "word",
      "position" : 3
    },
    {
      "token" : "海老蔵",
      "start_offset" : 6,
      "end_offset" : 9,
      "type" : "word",
      "position" : 4
    }
  ]
}

環境構築手順

elastic search6.8.1のインストール

elastic sudachi導入手順

elastic sudachi辞書配置

full辞書をダウンロードし、フォルダに配置する。

  • https://github.com/WorksApplications/Sudachi
  • 配置先:Windowsの場合 C:\ProgramData\Elastic\Elasticsearch\config\sudachi_tokenizer\system_core.dic(デフォルトはelastisearch config配下のsudachi_tokenizer/system_core.dicを参照します。)

見解

sudachiの構文解析の品質は良いと感じている。
full版の辞書を利用すると、辞書による固有名詞の理解が多くなり、分析面でメリットがある一方、
単語単位での分かち書きと固有名詞トークンが生成されるため、フレーズ一致の面でデメリットが生じる。

自社要件としては、漏れなくフレーズに一致できることが求められているため、small版辞書が要件を満たしそうだ。

sudachiは辞書が充実していることがウリだが、検索面では辞書によるデメリットも生じるため、辞書はsmallの方が挙動を理解しやすく思える。
辞書がsmallの場合、kuromojiに対する優位性は現在分かっていない。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

はじめまして。

modeをnormalにして、データを登録し直したらうごきませんか?
手元で7.6.0で動作させてみましたが、7.6.0の場合は、modeをnormalにしてデータ登録したところ、
検索にヒットしました。

searchのモードで動かないのは、まだ推測ですが、「代目」「代」「目」という1つの単語に対して複数のパターンが出てきてしまったあとに、単語を組み合わせたフレーズ「代目市川」などが問題かと思います。
validateクエリというAPIがあるので、これで、クエリが確認できます。
まだ、推測の域を出ていませんが、参考になればと。

GET mytestindex/_validate/query?explain
{
  "query": {
    "match_phrase": {
      "sudachi_field": "十一代目市川海老蔵"
    }
  }
}

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/03/01 03:44

    はじめまして、ご連絡ありがとうございます。

    normal search extended全て試してみましたけど、駄目でした。。
    1つの単語の複数展開は、フレーズマッチにはちょっと不向きですかね。。

    ただ、インデックス時と同じテキストでクエリしてるので、同じ解析結果になると思っていたのですが。。(分析用、検索用同じアナライザにしています)

    辞書がfullでなく、smallなら動くので、一旦はこちらで逃げようと思ってます。

    どうもありがとうございます。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.22%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る