倒排索引、分析和映射
date
Jul 29, 2021
slug
elasticsearch-guide-invert-index-and-analyse
status
Published
tags
Elasticsearch
读书
summary
type
Page
倒排索引 Inverted Index
一般使用倒排索引(inverted index)结构实现快速的全文检索。首先对下面两个句子拆成单词,生成不重复词条的排序列表
- The quick brown fox jumped over the lazy dog
- Quick brown foxes leap over lazy dogs in summer
此时如果搜索
quick brown
,我们只需要查找包含每个词条的文档:而且 Doc_1 能够匹配到两个词,所以相关度更好。
分词和标准化(tokenization and normalization)
上面的倒排索引还不够完美,比如:
Quick
和quick
以独立的词条出现,然而用户可能认为它们是相同的词。
fox
和foxes
非常相似, 就像dog
和dogs
;他们有相同的词根。
jumped
和leap
, 尽管没有相同的词根,但他们的意思很相近。他们是同义词。
可以对单词做一些标准化处理:
Quick
可以小写化为quick
。
foxes
可以词干提取变为词根的格式为fox
。类似的,dogs
可以为提取为dog
。
jumped
和leap
是同义词,可以索引为相同的单词jump
。
这样得到的倒排索引像这样:
之后对搜索的关键词做同样的标准化,如将搜索词
Quick
转换成 quick
的过程。分析和分析器 (Analysis and Analyzer)
分析 analysis 的过程主要做两件事情:
- 将文本分词成独立的单词,这样适用于建立倒排索引
- 将单独标准化提高单词的可搜索性,方便召回
而分析器 analyzer 就是做这件事的,分析器 analyzer 内部有三种功能组成
- 字符过滤器 character filters:字符串按顺序通过每个字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉 HTML,或者将 & 转化成 and。
- 分词器 tokenizer:字符串被分词器分成独立的词条 term,一般的分词器遇到空格或标点符号就算一个词条。
- Token 过滤器 token filters:这一步是将每个词条单独做处理,如小写化、移除停用词、添加同义词等。
当添加一个文档时,Elasticsearch 会对文档中全文字段做分析,从而建立倒排索引。
当搜索一个关键词时,Elasticsearch 会对关键词做分析,便于检索文档。
映射 Mapping
映射 Mapping 中可指定 field 的类型,如果类型是 text,还可以指定使用什么分析器:
保存数组类型
可以保存形如
{ "tag": [ "search", "nosql" ]}
的 field 类型,任何 field 都可以保存多个值无需特殊指定,也就是说此时的 tag 字段,其类型依旧是 text 类型,查看此时 blogs 的 mapping 可以看到:同样的,数组中每个元素的类型都必须满足 field 的定义,即 tag 中必须都是 text 类型,Elasticsearch 会使用第一个元素的类型作为整个 feild 的类型。
保存空类型
Lucene 中不能存储 null 值,下面三种 feild 会被认为是空的,不会被索引:
保存对象类型
形如在文档中加入 user 信息的形式:
查看其 mapping 结构:
由于 Lucene 不支持对象,所以 Elasticsearch 会把对象打平(flat),类似这样:
在数组中保存对象
处理形如下面这种文档:
也会被打平,不过不太一样的是会将每个属性放在一起打平:
这样的索引有个问题是,age 和 name 之间的联系丢失了。只能回答 ”Is there a follower who is 26 years old?“,但无法回答 ”Is there a follower who is 26 years old and who is called Alex Jones?“。要支持第二种查询,需要用到嵌套对象 nested object。
查询和过滤的区别 Query and Filter
查询问的问题是某文档对于搜索词的相关度怎么样,结果是相关度得分的高低。
过滤问的问题是某文档的字段是否满足某条件,结果是满足和不满足。
性能上来说,过滤性能会稍微好一些,除了全文搜索的字段,其他字段上的查询都应该使用过滤。
使用 explain 参数分析查询
相似度分数的计算
相似度分数有如下几个点影响:
- 搜索词在该字段出现的频率:出现频率越高,相关性也越高。 字段中出现过 5 次要比只出现过 1 次的相关性高。
- 搜索词在反向索引中出现的频率:频率越高,相关性越低。搜索词出现在多数文档中会比出现在少数文档中的权重更低。
- 字段的长度:长度越长,相关性越低。 搜索词出现在一个短的 title 要比出现在一个长的 content 字段权重更大。
同样可以通过 explain 参数查看评分的细节,甚至可以指定一个不 match 的文档 id,查看为什么不匹配。