最近在项目中有使用到 Elasticsearch,使用JAVA实现一个站内搜索微服务, 这玩意儿看似比较简单,开发其实过程比较艰辛,踩了不少坑,所以上手开发前,需要一些前置知识。

Elasticsearch是什么?

Elasticsearch是用Java开发的,基于Lucene库的搜索引擎。它提供了一个分布式、支持多租户的全文搜索引擎,具有HTTP Web接口和无模式JSON文档。

检索出内容带“前”的诗句

数据库中仅存在一条诗句的情况:

普通索引

1
2
3
4
5
6
7
key: 静夜思

value:
- 床前明月光
- 疑是地上霜
- 举头望明月
- 低头思故乡

如果将诗名作为key,诗内容作为value,由于数据量巨大,只能遍历诗句内容,查询效率低

倒排索引

1
2
3
4
5
key:前

value:
- 床前明月光
- 疑是地上霜

倒排索引以“前”作为索引,可以快速检索诗句内容中出含有“前”的诗

但也会存在一个问题,2行诗,所有的诗句内容都可以建立索引,共10个文字,可以建立10个索引

正向索引只有1个索引,反向却有10个,将导致索引量增加

解决方法:

是否可以进行数据压缩?

既然可以将诗名作为key,那么反向索引可以索引到诗名,而不是诗内容,达到减少索引数据量的目的。

1
2
3
4
5
6
7
8
9
key:床 -> value 静夜思

key:前 -> value 静夜思

key:明 -> value 静夜思

key:月 -> value 静夜思

key:光 -> value 静夜思

此时诗句的标题可以理解为正向索引,数据库中仅存在多条诗句的情况,可以实现为“索引矩阵”

1
2
3
4
5
key1:静夜思 -> values (前,月)

key2:望庐山瀑布 -> values (前)

key3:月下独酌 -> values (月)

其中 key1 和 key2 存在“前”,key3 存在 “月”

建立索引的时候可以这样:

1
2
3
4
5
6
7
key:前 - values
- 静夜思
- 望庐山瀑布

key:月 - values
- 静夜思
- 月下独酌

实现的效果是:搜索“前”,可以索引到2首诗,搜索“月”,可以索引到2首诗。

总结:搜索引擎的核心概念是建立倒排索引,快速命中所需要的内容。

停顿词过滤

有这样一段话:

面试官“的”每一个问题,都是有考察点的。但是对于这样的软问题,你可以好好回答来主导方向,要体现出你的深度思考,体现你在工作中如何创造价值,“而”不是浮于问题表面。

“的”、“而”,为无意义的停顿词,没有必要建立索引,也就是所谓的“分词”。

1
2
3
4
5
分词:面试官

建立反向索引是如何的?

key:面试官 - value:面试

搜索引擎过程

  • 爬取内容
  • 进行分词
  • 建立反向索引

Elasticsearch的三大概念

1
2
3
4
5
索引 = 与mysql的索引不同,在 Elasticsearch 中用于存放数据 (mysql的数据库)

类型 = 用于定义数据结构 (mysql的表)

文档 = 最终的数据 (mysql的行)

数据如何存储到Elasticsearch中?

例如:一首诗,有诗题目,作者,朝代,字数,内容等字段

我们可以先建立一个poems的索引,然后创建一个poem的类型,通过 Mapping 来定义类型中每个字段的类型

作者,朝代为 keyword 类型,内容为 Text 类型,字数为 Integer 类型

索引 poems

类型

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
"poem": {
"properties": {
"title": {
"type": "keyword"
},
"author": {
"type": "keyword"
},
"dynasty": {
"type": "keyword"
},
"words": {
"type": "integer"
},
"content": {
"type": "text"
}
}
}
}

文档

1
2
3
4
5
6
7
{
"title": "静夜思",
"author": "李白",
"dynasty": "唐",
"words": "20",
"content": "床前明月光,疑是地上霜,举头望明月,低头思故乡"
}

Keyword 和 Text 在 Elasticsearch 都表示为字符串

区别在于:

  • Keyword 类型不会进行分词,会直接根据内容建立反向索引
  • Text 类型在存入 Elasticsearch 的时候,先进行分词,然后根据分词后的内容建立反向索引

如何建立 Elasticsearch 索引?

Elasticsearch 把操作都封装成了 HTTP 的 API,我们只要给 Elasticsearch 发送 HTTP 请求即可。

学习Elasticsearch的关键在于掌握API。

总结

  • 反向索引又叫倒排索引,是根据文章内容中的关键字建立索引。
  • 搜索引擎原理就是建立反向索引。
  • Elasticsearch 在 Lucene 的基础上进行封装,实现了分布式搜索引擎。
  • 索引、类型、文档的概念比较重要,类似于 MySQL中的数据库、表和行。
  • Master-slave 架构,实现了数据的分片和备份。

写在最后

此文章参考 终于有人把Elasticsearch原理讲透了! 进行编写。