映射
Mapping用于描述数据的每个字段如何存储。ES自动生成一个_all字段,其类型为字符串,属于全文字段。ES会根据文档内容进行猜测,动态产生一个映射。
简单类型
Elasticsearch 支持 如下简单域类型:
- 字符串:string
- 整数:byte, short, integer, long
- 浮点数:float, double
- 布尔型:boolean
- 日期:date
当你索引一个包含新字段的文档时,ES自动进行动态映射。JSON类型到上述类型的转换比较直白,除了要注意2018-04-03这样的字符串会被自动解析为date类型。
复杂类型
除了上述的简单标量类型外,JSON中的null、数组、对象,都是被ES支持的。
空字段不会被索引,包括:null、null、[ null ]
Lucene不理解嵌套对象,Lucene文档由一组键值对的列表构成。为了支持复杂类型的处理,ES必须对文档进行扁平化。
多值域以数组形式表示,数组的元素类型必须相同。尽管提取文档时,数组元素顺序不会丢失,但是索引是以无序的多值域形式进行的:
Shell
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | { "followers": [ { "age": 35, "name": "Mary White"}, { "age": 26, "name": "Alex Jones"}, { "age": 19, "name": "Lisa Smith"} ] } # 被扁平化为 { # 扁平化后,age和name之间的关系丢失 # 如果要查询是否有名为alex的26岁的follower,需要使用嵌套对象 "followers.age": [19, 26, 35], "followers.name": [alex, jones, lisa, smith, mary, white] } |
类似的,为了让ES有效的索引嵌套对象,同样需要扁平化:
Shell
1 2 3 4 5 | { "tweet": [elasticsearch, flexible, very], "user.id": [@johnsmith], "user.gender": [male] }? |
分析
Analysis是处理全文字段,使其可以被搜索的过程。分析包含下面的步骤:
- 首先,将一块文本分成适合于倒排索引的独立的词条
- 之后,将这些词条统一化为标准格式以提高它们的“可搜索性”
分析器
分析器负责执行上面的工作。 分析器实际上是将三个功能封装到了一个包里:
- 字符过滤器:首先,字符串按顺序通过每个字符过滤器 。他们的任务是在分词前整理字符串。一个字符过滤器可以用来去掉HTML,或者将 & 转化成and
- 分词器:其次,字符串被分词器分为单个的词条。一个简单的分词器遇到空格和标点的时候,可能会将文本拆分成词条
- Token过滤器:最后,词条按顺序通过每个Token过滤器 。这个过程可能会:
- 改变词条,例如小写化?
- 删除词条,例如像 a, and, the这样的无用词
- 增加词条,例如像像 jump 和 leap 这种同义词
ES提供了开箱即用的字符过滤器、分词器、Token过滤器,它们可以自由的组合成分析器,满足不同应用场景。
内置分析器
分析器 | 说明 |
标准分析器 | 默认的分析器,根据Unicode联盟定义的单词边界来话分文本,删除绝大部分标点符号,最后小写化 |
简单分析器 | 在任何非字母的地方拆分词条 |
空格分析器 | 以空格为界拆分词条 |
语言分析器 | 针对特定语言,例如:
|
分析器何时生效
- 当索引一个文档时,它的全文域被分析成词条以用来创建倒排索引
- 当在全文字段上执行搜索时,查询字符串也需要类似的分析过程
当查询一个精确值字段时,分析器不会介入。
指定分析器
当ES在你的文档中检测到一个新的字符串域 ,它会自动设置其为一个全文字符串域,使用标准分析器对它进行分析。某些情况下你可能需要改变此默认行为:
- 你想使用一个不同的分析器,适用于你的数据使用的语言
- 你想要一个字符串域就是一个精确值,不需要分析
可以通过自定义映射来满足上述需求。
字段类型
总体来说,ES中的字段可以分为精确值、全文两个大类。
精确值包括日期、数字,字符串也可以表示精确值。精确值是大小写敏感的。精确值很容易查询,它要么匹配,要么不匹配查询条件。
查询全文字段则要复杂的多,通常不会对全文字段进行精确匹配查询。全文字段匹配查询条件时有个相关度的概念,表现为分数(Scoure)。搜索引擎应该能够识别缩写、词根、同义词,并给出适当的相关度。
对全文检索的支持依赖于分析,在分析之后需要创建倒排索引。
倒排索引
ES使用一种称为倒排索引的结构来支持快速的全文检索。
倒排索引的结构类似于RDBMS的位图索引,对于索引中出现的任何不重复的词的标准模式,生成包含该此的文档列表。标准模式提取了词干、同义词。
相关性
默认情况下,查询返回结果是按相关性倒序排列的。每个文档都有相关性评分,用一个正浮点数字段 _score 来表示 。 _score 的评分越高,相关性越高。
查询语句会为每个文档生成一个 _score 字段。评分的计算方式取决于查询类型。不同的查询语句用于不同的目的:fuzzy 查询会计算与关键词的拼写相似程度。terms 查询会计算找到的内容与关键词组成部分匹配的百分比。
通常我们说的 relevance 是我们用来计算全文本字段的值相对于全文本检索词相似程度的算法。ES的相似度算法被定义为检索词频率/反向文档频率, 包括以下内容:
- 检索词频率:检索词在该字段出现的频率?出现频率越高,相关性也越高
- 反向文档频率:每个检索词在索引中出现的频率?频率越高,相关性越低
- 字段长度准则:字段本身的长度是多少?长度越长,相关性越低