通过自己编写的字符转换插件,使Elasticsearch的日语搜索变得更加顺畅
首先
在Elasticsearch中有一個官方插件可以對日文進行形態解析。它非常方便地從長篇日文文章中提取出關鍵詞,但對於單詞數據或短日文可能不太擅長,有時候會出現問題。
例如,如果字符像”サイトウ”有几种写法,如”斉藤”、”斎藤”或”齋藤”,它们将无法完全匹配。
通过使用kuromoji_readingform词元过滤器,可以在很大程度上解决这个问题,但在使用它时,需要先使用kuromoji_tokenizer将每个词元分开。
请你考虑一下在搜索框中输入些什么,但是我认为这种搜索方式很少见。
我会这样做。
很多人希望自己能够决定搜索关键词的间隔,对吗?换句话说,
需要提前使用kuromoji_tokenizer将其分成每个令牌。
因为这个原因
Elasticsearch 自带日语搜索的自定义插件
希望查詢的狀況是這樣的
请提供一个原生中文的换句话:自制Elasticsearch日本语搜索插件。
如果数据被分割得像这样,而且搜索范围很大的话,只会出现大量垃圾数据在前面。
还有一点,在输入日语时,不是直接用汉字输入,而是先用假名输入然后再转换,对吧?
这样的话,在还没有转换成汉字之前,就无法得到预期的搜索结果,无法使用建议或增量搜索。
话虽说得有点长,但我们要解决的问题就在这里。
关于Elasticsearch的分析器
在Elasticsearch中,搜索词和搜索目标文档会通过分析器转化为便于搜索匹配的形式。详细内容可以在官方文档中找到,但简单概括来说,它由三个要素组成。
-
- 字符过滤器(char_filter)
-
- 分词器
- 过滤器(token filter)
按照这个顺序进行处理。
每个 char_filter 用于对整个字符串进行转换,tokenizer 用于将其分割为标记,filter 则用于对每个标记进行转换。
我想要关注的是 character filter 的结果进入 tokenizer 这一点。
kuromoji_readingform token filter 只能在 token_filter 中使用 kuromoji_tokenizer,但如果可以在 character filter 中使用它,就可以自由地切分令牌。
汉字→假名转换插件
所以,我想着一定有其他人也在考虑同样的事情!然后我试着寻找,但没找到,所以我自己制作了一个汉字转假名的插件。
在插件开发中,我参考了 Elasticsearch 官方提供的 elasticsearch-analysis-kuromoji。
安裝
在Docker上准备Elasticsearch并安装插件。
$ docker run --name=es -p9200:9200 -d elasticsearch:5.6.5
9b8458e2c86d1990aca9ef64a8111d0d169aac8524a88737c020db855f00c3e8
$ docker exec es bin/elasticsearch-plugin install https://github.com/bgpat/elasticsearch-analysis-japanese/releases/download/v0.0.1/elasticsearch-analysis-japanese-es5.6.5.zip
-> Downloading https://github.com/bgpat/elasticsearch-analysis-japanese/releases/download/v0.0.1/elasticsearch-analysis-japanese-es5.6.5.zip
[=================================================] 100%
-> Installed elasticsearch-analysis-japanese
我們還需要安裝 analysis-kuromoji 來進行比較分析。
$ docker exec es bin/elasticsearch-plugin install analysis-kuromoji
-> Downloading analysis-kuromoji from elastic
[=================================================] 100%
-> Installed analysis-kuromoji
因为插件在下次启动时才会生效,所以需要重新启动。
$ docker restart es
es
验证 (Verifying)
因为有用于验证分析器功能的 API,因此我们使用它。(由于使用 curl 命令写 JSON 很麻烦,所以我们用 Insomnia 进行验证)
默认设置
如果不指定任何内容,将使用标准分析器。
通过使用标准分词器加小写词元过滤器的组合,可以很好地对英文进行规范化处理。
当然,这种分析器无法处理日语。
kuromoji 分析器 (Kuromoji
我尝试使用Kuromoji分析器。
它可以将日语文本正规化得十分好。
检索的文件还可以(?),但是如果搜索词是这样的话会有困难。
使用kuromoji_tokenizer + kuromoji_readingform token filter
这次我们将解构Kuromoji分析器,并使用Kuromoji_readingform令牌过滤器将其转换为假名。
当然,使用Kuromoji分析器时几乎没有什么变化。
使用空格为分词器,结合Kuromoji_readingform为令牌过滤器。
我想要使用whitespace标记器进行空格分割,并在kuromoji_readingform标记过滤器中进行假名转换。
尽管有空格分隔,但卡纳转换没有生效。
空格分词器 + 片假名转换
空白分词器和自定义插件katakana_transform。
我实现了我想要的功能。
顺便试试看。
现在,即使名字「齐藤」的汉字记不太清楚,也可以通过搜索找到相应的信息了。
实例使用
我们在 http://syllabus.kstm.cloud/ 使用了新开发的插件。(我们使用了所属大学的课程大纲作为搜索对象的文档)
除了自制插件外,还可以通过 icu_normalizer 进行假名到罗马字的转换,以便在罗马字输入过程中进行增量搜索。此外,为了提高搜索速度,还通过 edge-ngram tokenizer 对目标文档进行索引。(由于使用了正则表达式,prefix 查询可能较慢)
虽然也使用了 kuromoji analyzer 来创建索引,但当完全匹配时,它一定会排在前面。
代码已放置在 https://github.com/kstm-su/es-syllabus-web 上。
总结
我介绍了一种不限制分词器的假名转换插件,可以进行个性化的日语搜索机制。
因为假名转换算法只能使用 ipadic-neologd 中的单词,所以我还不能满足,但我认为它可以适应大多数情况。