Elasticsearch教程(35) ik中文分词器+pinyin拼音分词器+同义词

您所在的位置:网站首页 ciu拼音对吗 Elasticsearch教程(35) ik中文分词器+pinyin拼音分词器+同义词

Elasticsearch教程(35) ik中文分词器+pinyin拼音分词器+同义词

2024-07-10 11:57| 来源: 网络整理| 查看: 265

1. 前言

闲来无事,发现上一篇ES博客还是去年9月份写的中文ik分词器 pinyin 首字母 search_as_you_type 组合使用,该篇文章还挖了一个大坑没有填,快一年了,是时候填下坑了。

2. 期望的效果

针对股票查询这个特点场景,再结合一般使用者的搜索习惯,暂时确定如下7种期望效果。

2.1 中文名称

在这里插入图片描述

2.2 全称拼音首字母

在这里插入图片描述

2.3 中文简称

在这里插入图片描述

2.4 简称拼音首字母

在这里插入图片描述

2.5 拼音

在这里插入图片描述

2.6 中文+拼音

在这里插入图片描述

2.7 股票编号

在这里插入图片描述

3. 放弃search_as_you_type类型

上一篇博客Elasticsearch教程(34)中介绍了search_as_you_type类型,通过反复的实验验证,感觉search_as_you_type类型并不符合当前的场景,主要是不够灵活,对于简称“中行”、“建行”的支持不好。所以放弃使用它了,转而使用IK分词器 + pinyin分词器。 search_as_you_type类型对“建设银行”的处理如下:

字段说明name按照 mapping 中的配置进行分析。 如果未配置分析器,则使用索引的默认分词器name ._2gram用大小为 2 的 shingle token filter 分词器进行分词name ._3gram用大小为 3 的 shingle token filter 分词器进行分词name ._index_prefix用 edge ngram token filter 包装上面的 name ._3gram 的分词器

下面对name = "建设银行"这个短语分析

字段分析后结果name“建” 、“设”、“银”、“行”name ._2gram“建 设”、“设 银”、“银 行”name ._3gram“建 设 银”、“设 银 行”name ._index_prefix“建”、"建 "、“建 设”、"建 设 "、“建 设 银” 等等 4. pinyin分词器的多音字的错误修改

网上关于pinyin分词器的安装和使用的博客特别多,这里我就不赘述了。但是我得说一个非常重要的问题,目前我写博客时最新的版本8.x还是有这样的问题。虽然GitHub上,已经有人提出了这个Issue,但是目前还没有修复,所以我们就自己动手手动改改吧。

就是多音字“银行”的“行”,pinyin分词器会把“yin hang”错误的转成“yin xing”,当你测试“中国银行”时它是对的,但是“建设银行”时就又错了。不信的话你自己试试看。

这个时候需要修改下图中的jar包解压出来 在这里插入图片描述 然后修改如下图中文件polyphone.txt,注意千万不要一下子把"yin xing"替换成"yin hang"。

因为“隐形”、“银杏”这些词的拼音就是"yin xing"。这个你需要手动一个一个看好了改,我不确定这个问题是nlp-lang的问题还是pinyin分词器作者改的问题,我看nlp-lang1.7的源代码这个文件里“银行”确实是对的"yin hang"。

改好后,再重新打成nlp-lang-1.7.jar包,替换上图的那个nlp-lang-1.7.jar文件,然后重启ES就行啦。 在这里插入图片描述

5. 配置同义词文件和自定义字典 1 同义词

在ES的config目录下,新建analysis文件夹,再创建synonyms.txt,配置如下同义词

建设银行,建行 中国银行,中行 中信证券,中信,中证 中水渔业,中渔,中水 苏州科达,科达 2 自定义字典

在ik的config目录下创建ext.dic文本文件,添加一些自定义的扩展词 在这里插入图片描述 修改如下的配置文件,指定扩展字典的文件名 在这里插入图片描述 上面操作执行好了后,一定要重启ES,否则是不生效的。

6. 设计ES文档结构

ES的文档设计如下,这就是一个简单的以学习为目的实验性设计,所以设计很简陋。

别人博客会设计tokenizer为ik,filter为pinyin,但是我实验下来不是很理想(针对我的场景而言)对于ik和pinyin我是分开的,中文+pinyin时用"name.pinyin",纯中文用"name.ik"或"name"对于name主字段,“analyzer”:“standard”,原因我在上篇博客解释了,有使用的场景对于name子字段,"keyword"特殊情况使用“firstLetter”,“shortName”,"shortNameFirstLetter"在代码中我没有用到,考虑后期优化先加着对于无需聚合和排序的keyword,加下"doc_values":false,出于性能优化的目的 PUT pigg_stock_base { "settings":{ "analysis":{ "analyzer":{ "pinyin_analyzer":{ "tokenizer":"my_pinyin" }, "ik_max_syno":{ "tokenizer":"ik_max_word", "filter":"my_synonym" }, "ik_smart_syno":{ "tokenizer":"ik_smart", "filter":"my_synonym" } }, "tokenizer":{ "my_pinyin":{ "type":"pinyin", "keep_first_letter":true, "keep_separate_first_letter":true, "keep_full_pinyin":true, "keep_original":false, "limit_first_letter_length":16, "lowercase":true, "remove_duplicated_term":true } }, "filter":{ "my_synonym":{ "type":"synonym", "synonyms_path":"analysis/synonyms.txt" } } } }, "mappings":{ "properties":{ "name":{ "type":"text", "analyzer":"standard", "fields":{ "keyword":{ "type":"keyword", "ignore_above":256, "doc_values":false }, "pinyin":{ "type":"text", "analyzer":"pinyin_analyzer" }, "ik":{ "type":"text", "analyzer":"ik_max_syno", "search_analyzer":"ik_smart_syno" } } }, "firstLetter":{ "type":"keyword", "doc_values":false }, "shortName":{ "type":"keyword", "doc_values":false }, "shortNameFirstLetter":{ "type":"keyword", "doc_values":false }, "code":{ "type":"keyword" } } } }

插入测试数据

PUT pigg_stock_base/_doc/1 { "name": "中国银行", "firstLetter": "zgyh", "shortName": ["中行"], "shortNameFirstLetter": ["zh"], "code": "601988" } PUT pigg_stock_base/_doc/2 { "name": "中国石油", "firstLetter": "zgsy", "shortName": ["中石油"], "shortNameFirstLetter": ["zsy"], "code": "601857" } PUT pigg_stock_base/_doc/3 { "name": "建设银行", "firstLetter": "jsyh", "shortName": ["建行"], "shortNameFirstLetter": ["jh"], "code": "601939" } PUT pigg_stock_base/_doc/4 { "name": "中信证券", "firstLetter": "zxzq", "shortName": ["中信","中证"], "shortNameFirstLetter": ["zx","zz"], "code": "600030" } PUT pigg_stock_base/_doc/5 { "name": "中信建设", "firstLetter": "zxjs", "shortName": [], "shortNameFirstLetter": [], "code": "601066" } PUT pigg_stock_base/_doc/6 { "name": "中水渔业", "firstLetter": "zsyy", "shortName": ["中水"], "shortNameFirstLetter": ["zs"], "code": "000798" } 7. 测试查询DSL语句 GET pigg_stock_base/_search { "query": { "match": { "name": { "query": "中水渔业", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name.pinyin": { "query": "中国银行", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name.ik": { "query": "建设银行", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name": { "query": "中国银", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name.pinyin": { "query": "中国银", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name.pinyin": { "query": "中国yh", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name.pinyin": { "query": "中国yinh", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name.pinyin": { "query": "中国yinhang", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name.pinyin": { "query": "zgyh", "operator": "and" } } } } GET pigg_stock_base/_search { "query": { "match": { "name.pinyin": { "query": "yh", "operator": "and" } } } } 8. 代码

对于后端代码我就不放了,因为是学习ES的代码,有很多地方要优化,我拼接ES查询语句用的是之前我博客Elasticsearch教程(27) ES拼接查询条件的工具类提到的工具,这次又加了matchAnd,主要是为了提供如下的查询:

GET pigg_stock_base/_search { "query": { "match": { "name": { "query": "中银行", "operator": "and" } } } }

前端我用的Vue3 + Element-Plus,其实今年我的学习的目标是啥也可以不学,但是一定要把Vue3学会使用。

export default { name: "StockBase" } import {ref, reactive} from 'vue' import {listStockBaseByKeyword} from '@/api/system/stockBase'; import {StockBase} from "@/types/api/system/stockBase"; const loading = ref(false); const options = ref([]) //const dataState = reactive({}); function handleSearch(keyword: string) { if (keyword) { loading.value = true; setTimeout(() => { loading.value = false listStockBaseByKeyword(keyword).then(({data}) => { options.value = data } ); }, 200) } else { options.value = [] } } 9. 结语

这个功能主要是为了学习ES的分词器的使用,后端代码有很多优化的地方,比如考虑用ES的异步查询或折叠查询collapse,所以没有必要放后端代码。

还有前端Vue3真的很重要,比Vue2添加了不少功能,光看文档不动手是没有用的,只有不断写页面才能真的学会前端。



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3