ElasticSearch入门:使用ES来实现模糊查询功能
ElasticSearch入门:使用ES来实现模糊查询功能
- 需求描述
- 方案设计
- 代码设计
- 测试中遇到的问题
- 总结与心得
需求描述
本文针对在工作中遇到的需求:通过es来实现模糊查询来进行总结;模糊查询的具体需求是:查询基金/A股/港股等金融数据,要求可以根据字段,拼音首字母,部分拼音全称进行联想查询;需要注意的是,金融数据名称中可能不止包含汉字,还有英文,数字,特殊字符等。
方案设计
常用的es模糊查询出于性能问题,官方建议是慎重使用的,但一般针对于与其他es查询相比,如果和其他搜索工具相比,es的模糊查询性能还是不错的;常见的模糊查询相关函数,例如wildcard,fuzzy,query_string等均不完全适配现有的业务需求,因此从另一个角度思考问题,拟采用更加灵活的分词器来解决多条件模糊查询问题。
ngram
分词器与传统的 standard
分词器或者是 ik
分词器相比,他的优点是可以分词出特殊字符,因此,在对字段查询时,可以采用 ngram
分词器;而对拼音全称以及首字母查询时,可以使用 keyword
与 拼音
结合的自定义分词。
代码设计
根据上述的方案设计,我们可以在es中定义这样一个索引:
settings:
{"analysis":{"analyzer":{"my_ngram_analyzer":{"tokenizer":"my_ngram_tokenizer"},"my_pinyin_analyzer":{"tokenizer":"keyword","filter":"py"}},"tokenizer":{"my_ngram_tokenizer":{"type":"ngram","min_ngram":1,"max_ngram":1}},"filter":{"py":{"type":"pinyin","first_letter":"prefix","keep_separate_first_letter":true,"keep_full_pinyin":true,"keep_joined_full_pinyin":true,"keep_original":true,"limit_first_letter_length":16,"lowercase":true,"remove_duplicated_term":true}}}
}mapping:
{"properties":{"name":{"type":"text","analyzer":"my_ngram_analyzer"},"fields":{"PY":{"type":"text","analyzer":"my_pinyin_analyzer","term_vector":"with_positions_offsets","boost":10.0}}}
}
以text = "恒生电子"为例,它的自定义拼音分词器 my_pinyin_analyzer
效果如下:
{"tokens": [{"token": "h","start_offset": 0,"end_offset": 4,"type": "word","position": 0},{"token": "heng","start_offset": 0,"end_offset": 4,"type": "word","position": 0},{"token": "恒生电子","start_offset": 0,"end_offset": 4,"type": "word","position": 0},{"token": "hengshengdianzi","start_offset": 0,"end_offset": 4,"type": "word","position": 0},{"token": "hsdz","start_offset": 0,"end_offset": 4,"type": "word","position": 0},{"token": "s","start_offset": 0,"end_offset": 4,"type": "word","position": 1},{"token": "sheng","start_offset": 0,"end_offset": 4,"type": "word","position": 1},{"token": "d","start_offset": 0,"end_offset": 4,"type": "word","position": 2},{"token": "dian","start_offset": 0,"end_offset": 4,"type": "word","position": 2},{"token": "z","start_offset": 0,"end_offset": 4,"type": "word","position": 3},{"token": "zi","start_offset": 0,"end_offset": 4,"type": "word","position": 3}]
}
而在对应的代码层面,出于对输入词的关联精确性与词语顺序的考虑,从match , match phrase 以及 match phrase prefix中选择match phrase来进行查询:
// 直接的字段匹配优先级大于拼音匹配
BoolQueryBuilder boolQueryBuilderKeyWord = QueryBuilders.boolQuery().matchPhraseQuery("name", imageStr).boost(2.0f)).should(QueryBuilders.matchPhraseQuery("name.PY", imageStr).boost(1.0f));
测试中遇到的问题
应用上述的代码于项目中,经过测试会发现一个问题:输入汉字会查询得出与汉字不相关但缩写一致的数据,例如:关键字录入"恒生电子",接口返回结果如下:
{"error_code": "0","error_info": "success","data": [{"en_prod_code": "600570.SH","secu_code": "600570","secu_abbr": "恒生电子","type": "A_stock","modification_time": "2022-04-22T19:47:37.000+00:00","en_abbr": "HSDZ"},{"en_prod_code": "007685.OF","secu_code": "007685.OF","secu_abbr": "华商电子","type": "fund","modification_time": "2022-04-22T19:41:38.000+00:00","en_abbr": "HSDZ"}]
}
通过检查发现,是代码中设置的查询语句有问题,将字段查询与拼音首字母查询隔离即可,即通过中文查询则只查询name字段,通过非中文查询则只查询name.PY,Java代码修改如下:
if (!imageStr.matches("(.*)[\u4e00-\u9fa5](.*)")) {BoolQueryBuilder boolQueryBuilderKeyWord = QueryBuilders.boolQuery().matchPhraseQuery("name.PY", imageStr);
} else {BoolQueryBuilder boolQueryBuilderKeyWord = QueryBuilders.boolQuery().matchPhraseQuery("name", imageStr);
}
最后,再次查询关键词“恒生电子",接口返回结果为:
{"error_code": "0","error_info": "success","data": [{"en_prod_code": "600570.SH","secu_code": "600570","secu_abbr": "恒生电子","type": "A_stock","modification_time": "2022-04-22T19:47:37.000+00:00","en_abbr": "HSDZ"}]
}
总结与心得
- es中的分词器虽然好用,并且性能优秀,但对于我们在平时的业务开发,还是需要考虑其与业务需求的适配性;虽然分词器可以自定义,但终究条件有限,需要理性种草与对待;
- 模糊查询业务中,除了实现方式以外,最重要的是关注查询字段的特性与要求,例如:有无查询特殊字符的需求,有无中英文混合查询的要求,有无根据中文词语语义联想的要求,有无排序查询优先级的需求等等,具体情况具体分析,无法一概而论。
ElasticSearch入门:使用ES来实现模糊查询功能相关推荐
- Elasticsearch(ES)数据库模糊查询source下的数据
Elasticsearch(ES)数据库模糊查询source下的数据: 1.先全部匹配查看一下数据: 查询数据结果如下: 由图可以看到 总共返回数据条数为:4297. 我们根据source下的id 模 ...
- pythonsqlite3模糊_Python编写通讯录通过数据库存储实现模糊查询功能
1.要求 数据库存储通讯录,要求按姓名/电话号码查询,查询条件只有一个输入入口,自动识别输入的是姓名还是号码,允许模糊查询. 2.实现功能 可通过输入指令进行操作. (1)首先输入"add& ...
- ajax jsp模糊查询源码,Ajax动态执行模糊查询功能
Ajax动态执行模糊查询功能 内容精选 换一换 Profiling采集的数据较多,同时解析后展示的性能指标项也比较多,为方便用户快捷查找到具体性能指标的含义,提供命令行查询功能:不包含metric_n ...
- js根据数据关键字实现模糊查询功能
js根据数据关键字实现模糊查询功能 模糊查询 实现模糊查询功能的步骤和一般方法 第一步:创建假数据或请求接口数据 第二步:分析数据格式,处理数据 第三步:验证功能 完整代码 模糊查询 模糊查询功能是指 ...
- TIPTOP 实现T100程序模糊查询功能
使用T100,在menu界面和Ctrl+G功能时,可以只输入部分字符或中文就可以将匹配的程序全部列出来供选择而TOP GP暂时还不支持这个功能,用惯了T100再回来用GP就很不习惯了,于是改善下,直接 ...
- ofice2007 没有下拉框模糊查询功能
ofice2007没有下拉框模糊查询功能 另外安装一下wps2019,换着用.
- html下拉菜单模糊查询,Select下拉框模糊查询功能实现代码
select下拉列表框支持输入模糊查询功能,设计非常的人性化,下面小编给大家分享了关键代码,大家根据自己的需求适当的添加修改,有任何问题欢迎给我反馈. 关键代码如下所示: 可输入的下拉框 var j ...
- ElasticSearch入门:ES分词器与自定义分词器
ES入门:ES分词器与自定义分词器 分词器的简单介绍 不同分词器的效果对比 自定义分词器的应用 分词器的简单介绍 分词器是es中的一个组件,通俗意义上理解,就是将一段文本按照一定的逻辑,分析成多个词语 ...
- bootstrap typeahead实现模糊查询功能
一:下载并引用 <script type="text/javascript" src="assets/js/bootstrap-typeahead.js" ...
最新文章
- 列举一些常见的系统系能瓶颈 Common Bottlenecks
- cassandra框架模型之二——存储机制 CommitLog 	MemTable SSTable
- 【Java核心计算 基础知识(第9版)】第3章 Java的基本程序设计结构
- 打印容器_化妆品行业是如何通过3D打印来定制开发产品的?
- ECMAScript6 新特性——“字符串的扩展”
- ASP.NET MVC 随笔汇总
- c++语言程序的结构特点,C++的特点(特性)
- vue 引入 less、scss、styles 全局样式变量
- stackoverflow favorites
- 架构设计工作笔记004---架构中常见的概念积累--随时更新
- 5G NR CSI Report中关于codebook/PMI的理解(1)
- 机器视觉检测技术之颜色视觉工具应用
- 云服务器搭建kms服务器-vol版本
- 基于单片机原理的暖风机控制系统设计-毕设课设资料
- Ajax 入门Demo
- three points 1(平面几何 三角形)
- php循环26个英文字母,有趣的真人字母操,形象生动容易学,帮孩子瞬间搞定26个英文字母,效果满分!...
- 【附源码】Java计算机毕业设计基于微信小程序停车系统(程序+LW+部署)
- 如何解决Win10删除文件慢的办法
- vscode ubuntu 环境下ssh 远程连接 不稳定 重新打开