搜索的时候,同样也会对关键词、或者说要搜索内容进行拆分,得到更多的关键词,然后去匹配 。假设我们想要根据 "校园爱情" 进行查找,那么会拆分成 "校园" 和 "爱情",然后直接就能得到 1、3、4、5,再根据 id 查找就可以了 。
之前是逐行遍历去确定记录,现在是先根据关键词来确定 id,而构建的关键词到 id 的映射便是倒排索引 。所以我们也可以发现,并不是说使用了 ES 之后就不需要数据库了 。因为数据库表的字段可能非常多,我们不会对每一个字段都建立倒排索引,而是只针对那些需要通过关键词匹配的字段,将该字段的每一行都拆分成一个个的关键词,然后再把所有的关键词组合起来,建立它们到 id 之间的映射(倒排索引) 。
因此在建立倒排索引后,行数反而会增多(如果大部分词都不一样的话),比如原来的数据有 100 万行,但是拆分出来的关键词有 200 万个,那么在建立倒排索引之后也会有 200 万行 。但我们不可能真的搜索 200 万次,有可能我们搜索一次就找到对应的 id 了,因为在倒排索引中匹配的是关键词 。
当然搜索一次是理想情况,也可能是十次、一百次,因此就需要设计一个好的搜索算法以及合适的数据组织结构来使得查询次数最小化,而算法如何设计显然不是我们需要操心的 。并且在倒排索引中进行关键词匹配也和数据库的 like 不一样,前者只需要匹配单词即可,效率要比后者高很多 。
以上便是全文检索以及倒排索引,还是很好理解的 。然后再来说说 Lucene,其实 Lucene 就是一个 Jar 包,里面封装了很多建立倒排索引、以及搜索相关的算法 。如果你使用 JAVA 语言的话,那么只需要引入这个 Jar 包,然后基于 Lucene 提供的 API 进行开发即可 。通过 Lucene 我们就可以对已有的数据建立索引,Lucene 会在本地磁盘上面组织数据的索引结构 。
什么是 ElasticSearch
了解了上面的内容之后,再来看 ES 就简单多了 。我们说 Lucene 它封装了类似于搜索引擎的功能,但它是部署在单机上面的,如果数据量非常大、需要多机存储的话该怎么办呢 。首先我们能想到的是把数据分散存储在多机上,然后每台机器各有一个 Lucene 。
上面的做法看似解决了数据量的问题,但其实背后还有很多缺陷,比如:
- 数据分散在多台机器上,这些数据要怎么切分?
- 当我们在搜索的时候 , 如果数据存在多台机器上,那么是不是每台机器都需要访问呢?显然这会很麻烦 。
- 数据一旦分散在多台机器上,那么如何保证建立高性能的索引?
- 数据的不丢失要如何保证,系统的高可用性要如何保证?
所以 ES 就应运而生,它是基于 Lucene 实现的一个搜索引擎,同样使用 Java 语言编写 。但是通过 ES 可以让全文搜索变得更加简单,因为 Lucene 需要你有比较深的检索相关的知识 , 比较复杂,而 ES 将这种复杂隐藏了起来,让用户可以通过 RESTful API 进行查询 。
不仅如此,ES 不仅仅是为了检索方便而封装的 Lucene,它还解决了分布式的问题 。因为 Lucene 只是一个库,如果想支持多机部署,那么你需要额外做很多的工作 。而 ES 把这些全部解决了,比如:
- ES 具有分布式的文件存储,每个字段都可以被索引、被搜索
- 自动维护数据在多个节点之间的分布,以及索引的建立、搜索请求的执行
- 自动维护数据的冗余副本,一个节点宕掉了,不会造成数据的丢失
- 可以轻松的扩展到上百台服务器,处理 PB 级结构化或非结构化数据
- 除了 Lucene 的检索功能,ES 还封装了更多的高级功能,比如聚合分析、基于地理位置的搜索等等,可以让我们快速的开发应用,如果要基于原生的 Lucene 实现是很困难的
推荐阅读
- 简易版的SpringBoot是如何实现的!!!
- 掌握Java并发编程,避免无处不在的竞态条件
- 什么是Python中的LEGB规则?
- 说一下MySQL主从复制的原理?
- 浅谈ArkUI之Web组件的基础用法
- 50 条实用的编写Python 程序建议
- 有什么好用的C/C++源代码混淆工具?
- 如何将加密的pdf解密?
- pdf怎么解密你知道吗?
- 今年的年休假没休完怎么办?