在Rails和Elasticsearch中创建搜索功能并尝试各种测试 – 同义词版

首先

本文是基于使用elasticsearch-rails的前提条件的文章。
文章中提到的示例和环境是基于Rails和Elasticsearch创建搜索功能并进行各种试验的基础上进行的-第一部分:基于示例应用程序的创建。

我想做的事情 (Wǒ zuò de

本次我们将介绍同义词的使用。
通过登记同义词,我们可以实现例如输入“ひろあか”来搜索“ヒーローアカデミア”的功能。

「悪魔の学園」

注册同义词的方式

在Elasticsearch中,注册同义词的方法大致有两种。

    • Synonymを定義したファイルを作成して、ファイルのパスをフィルターに定義する

 

    フィルターに直接Synonymの定義を登録する

我将使用样例代码来介绍使用这两种方法进行注册的方法。我会提供修正前的代码。

注册CustomAnalyzer

在注册Synonym时,需要在分析器(Analyzer)中添加过滤器(Filter)。因此,我们需要定义一个自定义的Analyzer,而不是使用内置的kuromoji分析器,并且在该分析器中添加过滤器。
首先,我们会在用于搜索处理的Concern中定义一个Analyzer。

module MangaSearchable
  extend ActiveSupport::Concern

  included do
    include Elasticsearch::Model

    index_name "es_manga_#{Rails.env}"

+   settings analysis: self.analyzer_settings do  # 追加したanalyzer_settingsメソッドでAnalyzerを登録する
      mappings dynamic: 'false' do
        indexes :id,                   type: 'integer'
        indexes :publisher,            type: 'keyword'
        indexes :author,               type: 'keyword'
        indexes :category,             type: 'text', analyzer: 'kuromoji'
+       indexes :title,                type: 'text', analyzer: 'custom_kuromoji' # 追加したAnalyzerを使う
+       indexes :description,          type: 'text', analyzer: 'custom_kuromoji' # 追加したAnalyzerを使う
      end
    end

  ・
  ・
  ・

  end

  ・
  ・
  ・

  class_methods do
  ・
  ・
  ・
    # Synonymを追加していくためのAnalyzerを定義。中身はビルドインのkuromojiをベースにしています
+   def analyzer_settings
+     {
+       analyzer: {
+         custom_kuromoji: {
+           type: 'custom',
+           char_filter: [],
+           tokenizer: "kuromoji_tokenizer",
+           filter: [
+             'kuromoji_baseform', 'kuromoji_part_of_speech',
+             'cjk_width', 'kuromoji_stemmer', 'lowercase'
+           ]
+         }
+       },
+     }
+   end
  end
end

使用文件进行同义词的注册

因为已经准备好了,所以从这里开始讨论Synonym。首先我们将进行基于文件的注册。

ひろあか,ヒロアカ => ヒーローアカデミア
てんすら,テンスラ => スライム

这次我们使用“=>”将左侧的单词替换为右侧的单词的写法,但也可以像“ひろあか,ヒロアカ,ヒーローアカデミア”一样,使用逗号分隔进行分组的方法。

当文件创建完成后,我们会将文件部署以便Elasticsearch进行读取,并对之前的分析器进行修改。

文件部署

将刚才创建的文件复制到容器内。

$ docker cp files/synonym.txt  elasticsearch_sample:/usr/share/elasticsearch/config/synonym.txt
# コピーしたファイルは必要に応じてElasticsearchから参照できるようにオーナーやパーミションを修正

修正了Analyzer。

我们将使用先前部署的synonym.txt文件来定义一个名为filter(manga_synonym)的过滤器,并将其添加到Analyzer(custom_kuromoji)的过滤器中。

module MangaSearchable

  ・
  ・
  ・

    def analyzer_settings
      {
        analyzer: {
          custom_kuromoji: {
            type: 'custom',
            char_filter: [],
            tokenizer: "kuromoji_tokenizer",
            filter: [
+             'manga_synonym', # 追加したfilterを先頭に追加
              'kuromoji_baseform', 'kuromoji_part_of_speech',
              'cjk_width', 'kuromoji_stemmer', 'lowercase'
            ]
          }
        },
+       filter: { # synonym用のfilterを追加
+         manga_synonym: {
+           type: 'synonym',
+           synonyms_path: 'synonym.txt',
+         }
+       }
      }
    end
  end
end

由于定义已经完成,我们将重新创建索引并重新插入数据。

$ docker exec -it rails_es_rails_1 /bin/bash
/app# bundle exec rake elasticsearch:create_index
/app# bundle exec rake elasticsearch:import_manga_all

如果以“ひろあか”进行搜索,我相信会得到与“ヒーローアカデミア”搜索结果相同的结果。

直接在过滤器中定义同义词

接下来我们来看一下直接在过滤器中定义的方法。

修正Analyzer

在中定义了一个名为filter(manga_synonym_2)的过滤器,并在其中直接定义了同义词。将定义的过滤器添加到分析器(custom_kuromoji)的过滤器中。

module MangaSearchable

  ・
  ・
  ・

    def analyzer_settings
      {
        analyzer: {
          custom_kuromoji: {
            type: 'custom',
            char_filter: [],
            tokenizer: "kuromoji_tokenizer",
            filter: [
              'manga_synonym', 
+             'manga_synonym_2', # 新たにfilterを追加
              'kuromoji_baseform', 'kuromoji_part_of_speech',
              'cjk_width', 'kuromoji_stemmer', 'lowercase'
            ]
          }
        },
        filter: {
          manga_synonym: {
            type: 'synonym',
            synonyms_path: 'synonym.txt',
          },
+         manga_synonym_2: { # filterを追加
+           type: 'synonym',
+           synonyms: [ # synonymsに直接登録していく
+             'すらだん => スラムダンク',
+           ]
+         },
        }
      }
    end
  end
end

由于定义已完成,我们需要重新创建索引并重新插入数据。

$ docker exec -it rails_es_rails_1 /bin/bash
/app# bundle exec rake elasticsearch:create_index
/app# bundle exec rake elasticsearch:import_manga_all

我认为,如果你在网上搜索“すらだん”,你应该会得到与搜索“スラムダンク”相同的结果。

总结

我介绍了使用elasticsearch-rails在Rails中使用同义词的方法。(这次的修正内容)
无论哪种方法都相对简单且方便。我认为,在单词数量增加时,可能需要一些维护方法的改进,但为了提高搜索准确性,我们应积极使用。

以下是参考的汉语编写版本:

自定义分析器 | Elasticsearch参考 [7.3] | Elastic
处理Amazon Elasticsearch服务中的同义词(Synonym) | DevelopersIO

bannerAds