dak ブログ

python、rubyなどのプログラミング、MySQL、サーバーの設定などの備忘録。レゴの写真も。

Elasticsearch での kuromoji での同義語辞書

2022-10-23 13:16:46 | elasticsearch
Elasticsearch で kuromoji に同義語辞書を適用する方法のメモ。
■同義語辞書
同義語辞書ファイルを相対パスで指定する場合には、elasticsearch をインストールしたディレクトリの
config ディレクトリが起点になります。
今回は elasticsearch/config/synonym/synonym_dic.txt に以下の内容を記載します。
にっぽん, ニッポン, 日本
書籍, 本
アメリカ => 米国

■インデックス定義(test_synonym.json)
{
  "settings": {
    "analysis": {
      "analyzer": {
        "ja_text_analyzer": {
          "tokenizer": "kuromoji_tokenizer",
          "type": "custom",
          "char_filter": [
            "icu_normalizer",
            "kuromoji_iteration_mark"
          ],
          "filter": [
            "kuromoji_readingform",
            "kuromoji_stemmer",
            "kuromoji_part_of_speech",
            "ja_stop",
            "kuromoji_stemmer",
            "synonym_dic"
          ]
        }
      },

      "filter": {
        "synonym_dic": {
          "type": "synonym_graph",
          "synonyms_path": "synonym/synonym_dic.txt"
        }
      }

    }
  },

  "mappings": {
    "dynamic": "strict",
    "properties": {
      "id": {
        "type": "keyword",
        "store": "true"
      },
      "title": {
        "type": "text",
        "store": "true",
        "analyzer": "ja_text_analyzer"
      },
      "body": {
        "type": "text",
        "store": "true",
        "analyzer": "ja_text_analyzer"
      }
    }
  }
}

■インデックス作成
上記のインデックス定義で test_synonym インデックスを生成します。
curl "http://localhost:9200/test_syononym?pretty" \
     -X PUT \
     -H 'Content-Type: application/json' \
     -T test_synonym.json

■登録データ(bulk_test_synonym.jsonl)
{"index": {"_id": "id_01"}}
{"id": "id_01", "title": "日本", "body": "日本の家"}

{"index": {"_id": "id_02"}}
{"id": "id_02", "title": "ヨーロッパ", "body": "ヨーロッパの本"}

{"index": {"_id": "id_03"}}
{"id": "id_03", "title": "アメリカ", "body": "アメリカのテレビ"}

{"index": {"_id": "id_04"}}
{"id": "id_04", "title": "米国", "body": "米国のラジオ"}

■データ登録
curl "http://localhost:9200/test_synonym/_bulk?pretty" \
     -X POST \
     -H 'Content-Type: application/x-ndjson' \
     -T bulk_test_synonym.jsonl

■検索(書籍)
「書籍」で検索すると、辞書の「書籍, 本」のエントリにより「本」にもヒットします。
curl "http://localhost:9200/test_synonym/_search?pretty" \
     --silent \
     -X GET \
     -H 'Content-Type: application/json' \
     -T '{"query": {"match": {"body": "書籍"}}}'

実行結果は以下の通り。
    "hits" : [
      {
        ...
        "_source" : {
          "id" : "id_02",
          "title" : "ヨーロッパ",
          "body" : "ヨーロッパの本"
        }
      }
    ]

■検索(アメリカ)
「アメリカ」で検索すると、辞書の「アメリカ => 米国」のエントリにより「米国」にもヒットします。
curl "http://localhost:9200/test_synonym/_search?pretty" \
     --silent \
     -X GET \
     -H 'Content-Type: application/json' \
     -T '{"query": {"match": {"body": "アメリカ"}}}'

実行結果は以下の通り。
    "hits" : [
      {
        ...
        "_source" : {
          "id" : "id_03",
          "title" : "アメリカ",
          "body" : "アメリカのテレビ"
        }
      },
      {
        ...
        "_source" : {
          "id" : "id_04",
          "title" : "米国",
          "body" : "米国のラジオ"
        }
      }
    ]

■検索3(米国)
「米国」で検索すると、辞書は「アメリカ => 米国」となっており、「米国」では「アメリカ」を同義語として参照しません。
curl "http://localhost:9200/test_synonym/_search?pretty" \
     --silent \
     -X GET \
     -H 'Content-Type: application/json' \
     -T '{"query": {"match": {"body": "米国"}}}'

実行結果は以下の通り。
    "hits" : [
      {
        ...
        "_source" : {
          "id" : "id_04",
          "title" : "米国",
          "body" : "米国のラジオ"
        }
      }
    ]