Elasticsearch 用的倒排索引,就是一种结构,或者说数据结构。
比如举个例子:想搜索 apple iphone
,Elasticsearch 默认的分词器会将这个搜索内容,切分为 apple
和 iphone
。
这也就是所谓分词器的作用,用来切词。没人使用的分词器 standard 标准分词器,是按照空格来切分的。
如果想使用中文,就需要安装ik分词器。对中文进行分词。
默认的 standard 分词器,比如 中国
,直接就切分成 中 和 国了。不会把中国看成是一个词。
举例:有这两个document
-
The quick brown fox jumped over the lazy dog
-
Quick brown foxes leap over lazy dogs in summer
创建倒排索引后,会把字段内容切分成每个词,并且标记在每个每个文档出现过。
Term Doc_1 Doc_2 ------------------------- Quick | | X The | X | brown | X | X dog | X | dogs | | X fox | X | foxes | | X in | | X jumped | X | lazy | X | X leap | | X over | X | X quick | X | summer | | X the | X | ------------------------
比如想搜索 quick brown
,只要找到哪个文档出现 quick
或者 brown
Term Doc_1 Doc_2 ------------------------- brown | X | X quick | X | ------------------------ Total | 2 | 1
这是官方给的例子。其实已经很明了了。
但是这里要注意个问题:quick brown
是搜索词,搜索时候是要被分词或切词的。
而document是创建倒排索引的时候被分词或切词的。
Doc_1 匹配到了两个词,Doc_2匹配到了一个词,这样Elasticsearch 会有一个相关度的评分算法,把Doc_1排到数据结果的上边。
当然还有一些其他问题,比如:
-
Quick 和 quick,作为单独的terms出现,而用户可能认为它们是同一个单词。
-
fox 和 foxes 他们是相似的,也还是一个意思。
-
jumped 和 leap , 他们的意思是一样的。
好像这三个问题,在中文里边没有场景会有问题吧!我得想想。
分析器也就做了一些事情
-
Quick 变成小写的 quick。
-
foxes 变成 fox, dogs 变成 dog。 英文里这叫单词的根状态吧!不知道,官方文档是这么解释的。
-
jumped 和 leap 就是同意词,都 term jump。
然后就变成这样:
Term Doc_1 Doc_2 ------------------------- brown | X | X dog | X | X fox | X | X in | | X jump | X | X lazy | X | X over | X | X quick | X | X summer | | X the | X | X ------------------------
可以相对再举个例子,那先说什么是正排索引。
Elasticsearch 搜索是用倒排索引,而排序和聚合就是正排索引。这里边牵扯到两个概念,一个是doc_value 另一个就是fieldata。
什么正排索引呢?
你可以把他想象成你执行了一条sql语句,在mysql 查询出来的结果应该是这个样子的:
ID 字段1 字段2 ------------------------- 1 | X | X 2 | X | X 3 | X | X 4 | X | X 5 | X | X 6 | X | X ------------------------
这就是正排索引,上边的例子存成倒排索引,就是这个样子的:
词项 文档 ID ------------------------- 词1 -> 1,2.... 词2 -> 2,3.... 词3 -> 1,3.... 词4 -> 1.... 词5 -> 2.... 词6 -> 3.... ------------------------