当前位置: 首页 > article >正文

ElasticSearch全文检索和倒排索引

本文内容参考了田雪松老师编著的《Elastic Stack应用宝典》

全文检索

先来解释一下什么叫全文检索。数据检索的目的是从一系列数据中,根据某一或某些数据特征将特定的数据找出来。从数据检索的角度来看,数据大体上可以分为两种类型:一种是结构化数据;另一种是非结构化数据。结构化数据将数据具有的特征事先以结构化的形式定义好,数据有固定的格式或有限的长度。典型的结构化数据就是传统关系型数据库的表结构,数据特征直接体现在表结构的字段上,所以根据某一特征做数据检索很直接,速度也比较快。比如,根据商品的名称将该商品全部查找出来,通过一条SQL语句就能实现。如果想要提高查找速度,只要在商品名称上创建索引就可以了。许多应用系统都是建立在结构化数据的基础之上,例如财务软件、CRM、MIS等。

非结构化数据则完全不同,它们没有预先定义好的结构化特征,也没有固定格式和固定长度。典型的非结构化数据包括文章、图片、视频、网页、邮件等,其中像HTML网页这种具有一定格式的文档也称为半结构化数据。显而易见,相比结构化数据,非结构化数据的检索要难得多。在对它们的检索中,像文章、网页、邮件这种全文本(Full-text)数据的检索需求占了大多数,而且与图片、视频等非文本数据的检索完全不同,因此形成了一门独立的学科,这就是全文检索。包括Elastic官方网站在内的很多文献中,经常称全文本数据为全文数据,称全文数据中的一条数据为文档(Document)​,而称存储全文数据的数据库为全文数据库。所以简单来说,全文检索是指在全文数据中检索单个文档或文档集合的搜索技术,而Elasticsearch从这个意义上来说也可以理解为是一个全文数据库。

与结构化查询相比,全文检索面临的最大问题就是性能问题。全文检索最一般的应用场景是根据一些关键字查找包含这些关键字的文档,比如互联网搜索引擎要实现的功能就是根据一些关键字查找网页。显然,如果没有对文档做特别处理,查找的办法似乎只能是逐条比对。具体来说就是先将所有文档都读取出来,再对文档内容做逐行扫描看是否包含这些关键字。例如,Linux中的grep命令就是通过这种算法实现的。但这种方法在数据量非常大的情况下就像海底捞针一样,速度一定会非常慢。而类似互联网搜索引擎这样的应用面对的文档数量往往都是天文数字,所以需要有一种更好的办法实现全文检索。

关系型数据库提升数据查询速度的常用方法是给字段添加索引,有了索引的字段会根据字段值排序并创建类似排序二叉树的数据结构(如B树)​,这样就可以利用二分查找等算法提升查询速度。所以在字段添加索引后,通过这些字段做查询时速度能够得到非常明显的提升。但由于添加索引后需要对字段排序,所以增加和删除数据时速度会变慢,并且还需要额外的空间存储索引。这是典型的利用空间换取时间的策略。普通的索引对全文检索并不适用,因为这种索引使用字段整体值参与排序,所以在检索时也要通过字段的整体值做查询条件。而全文检索一般是查询包含某一或某些关键字的文档,所以通过文档整体值建立的索引对提高查询速度是没有任何帮助的。为了解决这个问题,人们创建了一种新索引方法,这种索引方法就是倒排索引(Inverted Index)​。

倒排索引 

倒排索引先将文档中包含的关键字全部提取出来,然后再将关键字与文档的对应关系保存起来,最后再对关键字本身做索引排序。用户在检索某一关键字时,可以先对关键字的索引进行查找,再通过关键字与文档的对应关系找到所在文档。这类似于查字典一样,字典的拼音表和部首表就是关键字索引,而拼音表和部首表中的内容就是关键字与文档的对应关系。

有了倒排索引,用户检索就可以在倒排索引中快速定位到包含关键字的文档。倒排索引与关系型数据库索引类似,会根据关键字做排序。但关系型数据库索引一般是对主键创建,然后索引指向数据内容;而倒排索引则正好相反,它是针对文档内容创建索引,然后索引指向主键(文档一、文档二)​,这就是这种索引被称为倒排索引的原因。

不难看出,全文检索中提取关键字是非常重要的一步。这些预先提取出来的关键字,在Elasticsearch及全文检索的相关文献中一般称为词项(Term)​。文档的词项提取在Elasticsearch中称为文档分析(Analysis)​,是整个全文检索中较为核心的过程。这个过程必须要区分哪些是词项,哪些不是。对于英文来说,它还必须要知道apple和apples指的同一个东西,而run和running指的是同一动作。对于中文来说就更麻烦了,因为中文词语不以空格分隔,所以面临的第一难题是如何将词语分辨出来。


http://www.kler.cn/news/364508.html

相关文章:

  • Docker存储
  • 大语言模型数据类型与环境配置
  • stm32单片机基于rt-thread 的 串行 Flash 通用驱动库 SFUD 的使用
  • STMicroelectronics 意法半导体芯片选型表
  • 解锁PDF权限密码
  • 算法Day-9
  • 杂项笔记
  • 100种算法【Python版】第8篇——群体智能优化算法之人工蜂群算法
  • Docker容器的基础镜像:构建现代应用程序的基石
  • PYTHON实现麦克风实时传流语音听写
  • verilog函数和任务
  • 跳表:数据结构中的“快速通道”
  • 内容安全与系统构建加速,助力解决生成式AI时代的双重挑战
  • c# lambda表达式基础语法
  • java基础day04:方法(函数),练习
  • Android原生ROM出现WIFI显示网络连接受限,网络无法连接的问题
  • 一个vue3的待办列表组件
  • 【如何使用git将自己注释不上传到git服务器】
  • 博客搭建之路:hexo搜索引擎收录
  • pyflink 时序异常检测——PEWMA
  • 漏洞挖掘 | 记一次逻辑漏洞修改任意用户密码
  • 从0到1实现你自己的AI Chat应用
  • 密码学----RSA算法
  • Higress 云原生网关
  • JVM监控与调优工具
  • RabbitMQ最新版本4.0.2在Windows下的安装及使用