在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