Elasticsearch是什么?是一种NonSQL的存储,从名字上面可以看出,search表示最大的特点是在于搜索方面特别强大,elastic表示天然支持集群式部署的。从使用的角度讲,所有客户端和es的沟通都是的RESTful的http请求,传输的数据都是json格式的。
存储的基本单位是document,这可以看做是SQL DB里面的一条条记录。往上一层是type,相当于一个表,定义了document的结构。当然, 这个结构会比SQL DB的一个个字段要复杂一些。再往上一次是index,相当于DB schema,是最顶上的一层结构,拥有自己的各种setting。
为什么说elasticsearch搜索功能特别强大呢,因为在每个document插入到es中的时候都要进行索引(index)。这里的index是做动词,指的是讲文本内容做一些分析,处理最后生成一个个倒排索引(inverted index)。那么又为什么叫做倒排索引呢?听上去是普通的索引做了倒排序。其实不是的,要知道倒排索引,首先要知道正排索引(forward index)是长什么样的。
举个例子,现在有两个document,内容各有一句话
id: 1, content: "今天我要加班,别打扰我。"
id: 2, content: “今天我不加班,我要出去浪。”
这里去掉标点符号,利用里面的分词(term)作为index的值。索引生成完之后,要和原文建立对应关系,如下表,
Document Id | Index | Hit | Place |
---|---|---|---|
1 | 今天 | 1 | 1 |
1 | 我 | 2 | 2, 7 |
1 | 要 | 1 | 3 |
1 | 加班 | 1 | 4 |
1 | 别 | 1 | 5 |
1 | 打扰 | 1 | 6 |
2 | 今天 | 1 | 1 |
2 | 我 | 2 | 2, 5 |
2 | 不 | 1 | 3 |
2 | 加班 | 1 | 4 |
2 | 要 | 1 | 6 |
2 | 出去 | 1 | 7 |
2 | 浪 | 1 | 8 |
其中,Hit表示这个index在document中的出现次数,而Place指的是出现的位置。这个表格就是一个简易的正排索引的抽象。
在数据查询阶段,首先把待查询字符串做分词,然后把结果与索引进行匹配,遍历所有的document,然后根据索引关系依次找到每个document中包含的分词,与待查询的分词做比较,最后输出匹配到的document。
上述的动作在功能上是没有问题的,但是有两个主要的问题。第一,搜索的时候需要遍历所有的document,第二,即使一些document中存在相同的分词,比如上面的“今天”,“我”,“加班”,但是这些分词依然会再次被存储下来,因为正向索引的归类依据是document。
所以倒排索引与正排索引的区别就在于通过分词建立索引时的依据不同。倒排索引是在分词做完之后,先把索引项归类,比如下表,
Index | Document Id | Hit | Place |
---|---|---|---|
今天 | 1, 2 | 1, 1 | [1], [1] |
我 | 1, 2 | 2, 2 | [2, 7], [2, 5] |
要 | 1, 2 | 1, 1 | [3], [6] |
加班 | 1, 2 | 1, 1 | [4], [4] |
别 | 1 | 1 | [5] |
打扰 | 1 | 1 | [6] |
不 | 2 | 1 | [3] |
出去 | 2 | 1 | [7] |
浪 | 2 | 1 | [8] |
可以看出,这样的索引结构可以大大节省存储空间,因为文档越多,重合的分词也会越多,倒排索引的威力就越大。同时,在搜索的时候,只要遍历所有的倒排索引内的分词,就可以找到对应的document。所以,倒排索引是在文本搜索中很有效的数据结构。
Elasticsearch中建立倒排索引的过程会比上面的例子要复杂一些,大致的过程是这样,
在接触ES的时候很自然的会和SQL DB做比较,接下来会从SQL中的DDL和DML入手,看看ES是如何使用的。
这一系列的文章基于Elasticsearch版本5.1.2。