1.什么是同义词查询

ES(Elasticsearch)作为一个开源的、高扩展的分布式全文检索引擎,具有近实时的索引、搜索和分析等优点。用户在使用ES时,主要青睐其快速的查询性能。不同于传统的数据库,它具有非常灵活的查询方式,不但支持精确查询、模糊匹配、聚合查询等传统的数据查询方式,而且支持同义词查询。同义词查询,顾名思义就是根据相同意思的词进行查询,比如数据库里面存储的数据为“马铃薯”,我们不仅可以通过关键字“马铃薯”匹配到该数据,还可以通过关键字“土豆”得到我们想要的数据(“马铃薯”),该功能可以让查询更加的全面、方便和快捷,可以让用户体会到“随心所欲”般的查询快感,迫不及待的小伙伴赶快行动起来吧。

2.同义词查询解决了什么问题

同义词查询可以根据同义或近义词进行查询,它的使用主要针对以下两种应用场景:

  1. 获取一个词汇的同义词,比如搜索:京东,获取的结果:京东,淘宝,拼多多……。
  2. 获取一个词汇的同义词汇总,比如搜索:京东、淘宝或者拼多多,获取结果:电商平台。

对于场景一,如果不使用同义词查询,可能会有查询条件太苛刻,以及查询结果不全面等问题。例如某银行推出的有京东联名信用卡,在业务搜索关键字“京东”的时候,业务人员更想看到与京东联名卡相关的信息,所以仅仅返回京东相关的数据是不全面的,使用同义词搜索可以返回京东及京东联名卡的所有数据,这样可以更加全面得到我们想要的数据。

对于场景二,如果不使用同义词查询,可能需要存储更多的数据,浪费存储空间。例如某些项目仅仅需要电商平台的一些公共数据,而在搜索时,我们搜索不同的电商平台就需要存储不同电商平台的数据,造成存储浪费,使用同义词查询仅需要存储一份数据,搜索不同电商平台会得到同一个结果,可以更加准确、方便的得到我们需要的数据,使得查询条件更加宽泛。

ES集群在同义词配置时,传统模式是在analysis文件夹下面创建一个synonym文件,当用户创建索引时,指定同义词文档地址,搜索时会自动加载本地文件。传统模式为离线模式,需要在每个ES节点上面都配置一份一模一样的synonym文件,且每次进行更改或追加操作时,需要重启集群才能生效,这对于大数据平台来说是不符合实际的。为了实现同义词的热加载,我们开发了同义词服务器,只需把同义词文档synonym放在服务器上一份即可,每次更改或追加操作都会在自己设置的时间间隔之后生效,这样不但使集群使用者使用更加方便,而且对于集群维护人员也极大的减少了工作量,提高了集群的可用性。

3. ES同义词查询原理

ES同义词查询基于ES的分词原理,ES的分词原理可以查看之前的文章:让搜索引擎更懂你-Elasticsearch自定义分词开发实践,本文不再赘述,这里仅对ES同义词查询的原理进行介绍。

数据index到ES集群的过程依次为字符过滤器(Character filter)、分词器(Tokenizer)和Token过滤器(Token filter)。一个Analyzer可以包括多个Character filter、一个Tokenizer和多个Token filter,Character filter 用于分词前对原搜索的句子进行处理, Tokenizer 用于将搜索的句子分成多个词组,Token filter 用于处理Tokenizer输出的词组,比如删除某些词,修改某些词,增加某些词。

同义词查询的关键是自定义Token filter。该filter在收到Tokenizer发来的数据时,首先会获取synonym文件,比对Tokenizer处理后的词组,当出现同义词时,就按照synonym文件规则选定待搜索的词组,进行同义词搜索。ES在创建索引时进行预先设置同义词filter,并制定该filter为索引的Token filter,创建过程如下图所示:

上面的例子是在名为synonym的index下面创建了名为ik_sync_smart的分析器,该分析器的tokenizer为ik_smart, filter为word_sync.,word_sync是自定义Token filter,该filter的type是synonym,synonyms_path是指定的同义词词典的路径。

4.自定义同义词服务开发

Synonym Server的开发需要满足以下两点:

  1. 该 http 请求需要返回两个头部(header),一个是 Last-Modified,一个是 ETag,两者都是字符串类型,只要有一个发生变化,ES就会去抓取新的同义词。
  2. 该 http 请求返回的内容格式是一行一个同义词,换行符用\n 。

满足以上两个条件之后,可以把更新的同义词文档放到一个UTF-8编码的.txt文件中,当该文件中的内容发生变化时,Synonym Server 会在客户端请求该文件时自动返回相应的 Last-Modified 和 ETag,ES集群默认每隔60s请求一次server获取该文件,用户也可以在在创建索引时自己设定时间间隔,第一次请求该文件时,ES会把返回的Last-Modified 和 ETag放在本地,等到再次请求时,一旦发现Last-Modified 和 ETag中任一个发生变化,ES就会把synonym文件下载到集群中,如果Last-Modified 和 ETag都没有发生变化,便不会重新加载数据。

Synonym Server的开发中,Last-Modified使用了文件更改的最后时间,ETag记录了文件内容的hash值。

outputStream.write(data.getBytes("utf-8"));
response.setHeader("ETag", data.hashCode() + "");
response.setHeader("Last-Modified", date + "");
response.setHeader("Content-Length", file.length() + "");

与分词Server不同的是,Synonym Server还需要设置文件类型为text/plain。

response.setContentType("text/plain");

最后,文件以流的形式写入到Response中,写入到ES集群中。

String line;
StringBuffer sb = new StringBuffer();
while ((line = bufferedReader.readLine()) != null) {
    sb.append(line);
    sb.append("\n");
}
String data = sb.toString();

outputStream.flush();
bufferedReader.close();
inputStreamReader.close();
fileInputStream.close();

SSynonym Server也支持用户进行手动更新或追加自己的同义词文档或上传自己的同义词文件到远程仓库中,做到动态更新同义词词典的功能。

5.结果展示

5.1环境准备

自定义同义词服务采用SpringBoot进行开发,通过配置文件方式配置服务启动端口、synonym地址等信息,服务启动方式:java –jar Synonym-1.0-SNAPSHOT.jar

服务启动之后,需要创建同义词索引。创建索引时,需要创建自定义的filter,例如我们创建一个名为zyf3的索引:

图中红色标注部分为自定义filter,与离线同义词解析方式不同,这里synonyms_path为服务器的IP、端口号和资源请求接口,interval代表修改synonym文件之后ES请求同义词文档的时间间隔。

自定义filter完成之后,在索引的settings中设置了该索引的Analyzer,Analyzer在文章让搜索引擎更懂你-Elasticsearch自定义分词开发实践有详细的介绍,这里自定义了一个analyzer,设置该analyzer的分词(Tokenizer)为IK的Ik_max_word算法,并指定Token filter为自定义的filter(remote_synonym)。

索引zyf3仅预定义了一个字段(STANDER_COMP_NAME),类型为text,并指定该字段的analyzer为自定义的analyzer(synonym)。

索引创建完成,接下来我们分别对上面的两种场景进行结果演示。

5.2场景一

首先,我们在synonym.txt文件中追加一行:

京东,淘宝

经过30s之后,ES集群开始加载synonym文件。

从上图可以看出,同义词“京东”和“淘宝”已经加载成功,由于同义词服务的优点之一是不用重启集群,synonym文件会自动生效,所以我们直接对zyf3进行查询。

上图直接使用了自定义的analyzer(synonym)对“京东”和“淘宝”分别进行查询分析,最后的得到的结果相同,即无论我们查询“京东”还是“淘宝”,因为它们两个在synonym文件中定义的是同义词,所以查询分析两个词是等价的。

从这个结果也可以看出,对于文章开头提出来的场景一,同义词服务可以很完美的解决出现的问题,使得查询可以更加全面得到我们想要的数据。

5.3场景二

同样,我们首先对synonym文件进行修改,使得同义词适合于场景二,这里我们同样定义“京东”和“淘宝”为同义词,但它们都归属于“平台”,具体的synonym文件添加如下信息:

京东,淘宝 => 平台

同样不需要对集群和索引进行操作,经过30s之后,集群自定加载synonym文件。

从图中可以看出,同义词加载成功,我们直接查询分析“京东”和“淘宝”,查询结果如下:

同样分别对“京东”和“淘宝”进行查询分析,从图中可以看到,最后的结果是完成一样的,都是返回结果“平台”,即返回同义词的汇总结果。

从这个结果中,可以看出同义词服务可以很好的解决场景二出现的问题,通过同义词查询,可以更加准确、方便的得到我们需要的数据,使得查询条件更加宽泛。

6.遇到的问题

本次主要是SynonymServer和SynonymClient的开发,在开发和使用过程中,出现一些问题,总结如下:

  1. IkServer接口返回的response需要指定ContentType,否则会出现ES请求接口时,加载词典失败。
  2. 同义词查询需要和自定义分词相结合使用,如果在synonym文件中定义的同义词被IK分词器进行了切分,那么同义词查询将会出现查询不到的情况,所以自定义同义词最好也同时出现在自定义分词文件中。

7.总结与展望

本文重点讲解什么是同义词查询、同义词查询解决了什么问题、原理以及开发的过程细节,最后对不同场景的结果进行了展示。可以看到,自定义同义词查询可以更好的对数据进行查询,可以使查询性能更加的全面、快捷、准确。本文是让搜索引擎更懂你-Elasticsearch自定义分词开发实践的续集,里面有很多的概念都在该文中做了详细介绍,如果小伙伴遇见什么不懂的概念,可以研读该文章,如果大家有什么问题或建议,也欢迎大家积极与我们联系、沟通,共同学习。

作者:张亚飞

参考文献:

Elasticsearch Plugins and Integrations [7.10] | Elastic

Elasticsearch学习笔记6: 同义词搜索实现_weixin_34112181的博客-CSDN博客

https://blog.csdn.net/yexiaomodemo/article/details/86519753

《Elasticsearch源码解析及优化实战》

更多交流,欢迎关注我个人公众号“数匠笔谈”

Elasticsearch之自定义同义词开发实践相关推荐

  1. Android组件化开发实践(九):自定义Gradle插件

    本文紧接着前一章Android组件化开发实践(八):组件生命周期如何实现自动注册管理,主要讲解怎么通过自定义插件来实现组件生命周期的自动注册管理. 1. 采用groovy创建插件 新建一个Java L ...

  2. WCF分布式安全开发实践(6):传输安全模式之自定义X509Certificate证书验证

    今天继续WCF分布式安全开发实践(6):传输安全模式之自定义X509Certificate证书验证.本文介绍的内容主要是:主要是传输安全模式的UserNamePassword身份验证方式,基于WSHt ...

  3. 基于MaxCompute+开放搜索的电商、零售行业搜索开发实践

    简介:搜索一直是电商行业流量来源的核心入口之一,如何搭建电商行业搜索并提升搜索效果,一直是电商行业开发者努力攻克的难题.基于传统数据库或开源引擎虽然能够搭建基础搜索服务,但随着商品数据的增多和业务流量 ...

  4. Angular开发实践(一):环境准备及框架搭建

    引言 在工作中引入Angular框架将近一年了,在这一年中不断的踩坑和填坑,当然也学习和积累了很多的知识,包括MVVM框架.前后端分离.前端工程化.SPA优化等等.因此想通过Angular开发实践这系 ...

  5. 58同城 Elasticsearch 应用及平台建设实践

    分享嘉宾:于伯伟 58同城 高级架构师 编辑整理:陈树昌 内容来源:DataFunTalk 导读:Elasticsearch是一个分布式的搜索和分析引擎,可以用于全文检索.结构化检索和分析,并能将这三 ...

  6. COM组件开发实践(八)---多线程ActiveX控件和自动调整ActiveX控件大小(下)

    源代码下载:MyActiveX20081229.rar 声明:本文代码基于CodeProject的文章<A Complete ActiveX Web Control Tutorial>修改 ...

  7. 20189208杨晨曦《移动平台开发实践》第9周学习总结

    <移动平台开发实践>第9周学习总结 教材学习内容总结 课堂笔记-正则表达式 ab+:a+一个以上的b *:0次或多次 普通字符:字母数字下划线 \d:数字0-9 \w:字母数字下划线 \s ...

  8. Vue.js组件化开发实践

    Vue.js组件化开发实践 前言 公司目前制作一个H5活动,特别是有一定统一结构的活动,都要码一个重复的轮子.后来接到一个基于模板的活动设计系统的需求,便有了一下的内容.首先会对使用Vue进行开发的一 ...

  9. 让Elasticsearch飞起来!——性能优化实践干货

    让Elasticsearch飞起来!--性能优化实践干货 2018年12月19日 23:01:39 铭毅天下(公众号同名) 阅读数:8805更多 所属专栏: 深入详解Elasticsearch 版权声 ...

最新文章

  1. Linux内核——百度百科
  2. 一个完整的mybatis项目,包含增删改查
  3. oracle 转换成csv文件,如何将csv转换为oracle中的表
  4. python闭包的应用场景_Python闭包函数定义与用法分析
  5. python软件下载3版本-Python3.9下载
  6. vue2.0 + vux (四)Home页
  7. Docker 命令总结
  8. 用友NC6.5 ,NC6.33,NC 6.3最新补丁下载
  9. 苹果app代码行数统计
  10. 计算机 在电厂的应用,计算机自动控制系统在火电厂中的应用
  11. 计算机软考软件设计师知识点:软件可行性研究报告
  12. 给对象添加一个新对象
  13. CentOS8安装Docker服务
  14. android netd和kernelframeworks的通信逻辑
  15. Cisco测试命令和TCP/IP连接故障处理整理集合
  16. 橘子学java之java中的协程
  17. Linux时钟管理clk devm_clk_get clk_prepare_enable等学习
  18. Predis的一些操作汇总
  19. 基于希克斯需求价格弹性计算_西方经济学(微观部分)计算题
  20. 终于通关《光环:致远星》,结局竟然是。。

热门文章

  1. 秉火429笔记之十六 I2C--操作EEPROM
  2. unicode 生僻字_生僻字打不出来怎么办小编教你解决办法
  3. 西医综合记忆手册(太强了,这帮狂人。真败给他们了~~~)
  4. 笔记--javascript对象及简单,复杂数据类型
  5. 17届智能车-电磁组比赛心得一
  6. 修改演武今日可用数据显示
  7. 2020安徽省大学生程序设计大赛题解——K 农夫打狼
  8. 心脏支架手术后遗症 做完心脏支架手术留下后遗症
  9. mysql逻辑运算符的优先顺序_布尔逻辑算符的类型和在检索式中优先执行的顺序...
  10. python判别分析_二次判别分析Quadratic Discriminant Analysis(QDA)