一、确切值(Exact values) vs 全文文本(Full text)
Elasticsearch中的数据可以大致分为两种类型
- 确切值,确切值是确定的,正如它的名字一样。比如一个date或用户ID,需要精确匹配,对于2019-11-8,只输入2019-11是不能被检索出来,必须精确匹配
- 全文文本,Elasticsearch会对文本分析(analyzes),然后使用结果建立一个倒排索引,比如,可以支持模糊匹配,忽略大小写,近义词匹配
二、Elasticsearch分析器
分析器需要完成以下分析过程:
- 表征化一个文本块为适用于倒排索引单独的词(term)
- 然后标准化这些词为标准形式,提高他们的“可搜索性”
ES分析器组成:
- 字符过滤器
首先字符串经过过滤器(character filter),他们的工作是在表征化前处理字符串。字符过滤器能够去除HTML标记,或者转化为“&”为“and” - 分词器( Tokenizers ) 可以根据空格或逗号将单词分开
分词器(tokenizer)被表征化为独立的词。一个简单的分词器(tokenizer)可以根据空格或逗号将单词分开(注:这个在中文中不适用) - 标记过滤器 ( token filters )
每个词都通过所有表征过滤(token filters),可以修改词(例如将“Quick”转为小写),去掉词(例如停用词像“a”、“and”、“the”等等),或者增加词(例如同义词像“a”、“and”、“the”等等)或者增加词(例如同义词像“jump”和“leap”)
内置分析器
- 标准分析器,Elasticsearch默认使用的分析器,它是分析各种语言文本最常用的选择,根据 Unicode 联盟 定义的 单词边界 划分文本。删除绝大部分标点。最后,将词条小写
- 简单分析器,在任何不是字母的地方分隔文本,将词条小写
- 空格分析器,在空格的地方划分文本
- 语言分析器,可以考虑指定语言的特点
什么时候使用分析器?
当我们索引一个文档,它的全文域被分析成词条以用来创建倒排索引。 但是,当我们在全文域搜索 的时候,我们需要将查询字符串通过 相同的分析过程 ,以保证我们搜索的词条格式与索引中的词条格式一致
- 当你查询一个全文域时, 会对查询字符串应用相同的分析器,以产生正确的搜索词条列表。
- 当你查询一个精确值域时,不会分析查询字符串,而是搜索你指定的精确值
三、映射介绍
数据库中的表,我们一般在DDL语句中为每个字段指定存储类型,例如:varchar,int,datetime等等,目的很明确,就是更精确的存储数据,防止数据类型格式混乱
类比数据库,ES的索引字段也需要为其指定类型,它就像数据库中的 schema,这种在ES称为映射(mapping)
映射是定义一个文档及其包含的字段如何存储和索引的过程,可以从以下几个方面理解:
- 将哪些字符串字段视为全文字段
- 哪些字段包含数字,日期或地理位置
- 日期值的格式
- 自定义规则以控制动态添加字段的映射
动态映射: 文档写入es时,es可根据写入内容的类型自动识别,生成mapping
静态映射: 手动为索引指定字段类型
四、字段类型
JSON格式的数据 | 自动推测字段类型 |
null | 没有字段被添加 |
true or false | boolean |
浮点类型数字 | float类型 |
数字 | long类型 |
JSON对象 | object类型 |
数组 | 由数组中第一个非空值决定 |
string | 有可能是date类型(开启日期检测)、double或long类型、text类型、keyword类型 |
text 和 keyword 的区别:
- text 用于索引全文值的字段,例如电子邮件正文或产品说明。这些字段是analyzed,它们通过分词器传递 ,以在被索引之前将字符串转换为单个术语的列表。分析过程允许Elasticsearch搜索单个单词中 每个完整的文本字段。文本字段不用于排序,很少用于聚合
- keyword 用于索引结构化内容的字段,例如电子邮件地址,主机名,状态代码,邮政编码或标签。它们通常用于过滤,排序,和聚合。keyword字段只能按其确切值进行搜索。如果您需要索引电子邮件正文或产品说明等全文内容,则可能应该使用text字段
有时候单纯的一个字段类型满足不了我们复杂的需求,为了不同的目的,以不同的方式索引同一个字段通常很有用,例如,对于字符串字段,我们既可以将它映射为text类型用于全文搜索,亦可以将它映射为keyword类型用于排序或聚合,或者,还可以使用标准分词器、英语分词器和其他语言分词器索引文本字段
前面说过,当 Elasticsearch 遇到文档中以前 未遇到的字段,它用 dynamic mapping 来确定字段的数据类型并自动把新的字段添加到类型映射。
如果不希望这样,可以使用dynamic参数设置
- true,动态添加新的字段
- false,忽略新的字段
- strict,如果遇到新字段抛出异常
配置参数 dynamic 可以用在根 object 或任何 object 类型的字段上。你可以将 dynamic 的默认值设置为 strict , 而只在指定的内部对象中开启它, 例如:
PUT /my_index
{
"mappings": {
"my_type": {
"dynamic": "strict",
"properties": {
"title": { "type": "string"},
"stash": {
"type": "object",
"dynamic": true
}
}
}
}
}
- 如果遇到新字段,对象 my_type 就会抛出异常
- 内部对象 stash 遇到新字段就会动态创建新字段
参考
Elasticsearch权威指南