ElasticSearch 数据类型
类型一览表
一级分类 | 二级分类 | 具体类型 | 使用 |
---|---|---|---|
核心类型 | 字符串类型 | string,text,keyword | 结构化搜索,全文文本搜索、聚合、排序等 |
整数类型 | integer,long,short,byte | 字段的长度越短,索引和搜索的效率越高。 | |
浮点类型 | double,float,half_float,scaled_float | ||
逻辑类型 | boolean | ||
日期类型 | date | ||
范围类型 | range | ||
二进制类型 | binary | ||
复合类型 | 数组类型 | array | |
对象类型 | object | ||
嵌套类型 | nested | ||
地理类型 | 地理坐标类型 | geo_point | |
地理地图 | geo_shape | ||
特殊类型 | IP类型 | ip | |
范围类型 | completion | ||
令牌计数类型 | token_count | ||
附件类型 | attachment | ||
抽取类型 | percolator |
文本类型
text
全文类型
- description
用于索引全文值的字段。使用文本数据类型的字段,它们会被分词,在索引之前将字符串转换为单个术语的列表(倒排索引),分词过程允许ES搜索每个全文字段中的单个单词。文本字段不用于排序,很少用于聚合(重要的术语聚合是一个例外)。什幺情况适合使用text datatype,只要不具备唯一性的字符串一般都可以使用text,例如:电子邮件正文,商品介绍,个人简介 - parameter
- analyzer:指明该字段用于索引时和搜索时的分析字符串的分词器(使用search_analyzer可覆盖它)。 默认为索引分析器或标准分词器
- fielddata:指明该字段是否可以使用内存中的fielddata进行排序,聚合或脚本编写?默认值为false,可取值true或false。(排序,分组需要指定为true)
- fields:【多数类型】text类型字段会被分词搜索,不能用于排序,而当字段既要能通过分词搜索,又要能够排序,就要设置fields为keyword类型进行聚合排序。
- index:【是否被索引】设置该字段是否可以用于搜索。默认为true,表示可以用于搜索。
- search_analyzer:设置在搜索时,用于分析该字段的分析器,默认是【analyzer】参数的值。
- search_quote_analyzer:设置在遇到短语搜索时,用于分析该字段的分析器,默认是【search_analyzer】参数的值。
- index_options:【索引选项】用于控制在索引过程中哪些信息会被写入到倒排索引中
- docs:只索引文档号到倒排索引中,但是并不会存储
- freqs:文档号和关键词的出现频率会被索引,词频用于给文档进行评分,重复词的评分会高于单个次评分
- positions:文档号、词频和关键词
term
的相对位置会被索引,相对位置可用于编辑距离计算和短语查询(不分词那种) - offsets:文档号、词频、关键词
term
的相对位置和该词的起始字符串偏移量
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-I265lsjS-1599834691551)(en-resource://database/2637:1)]
首先创建 test_index
索引,设置其字段为全文类型,并设置其索引选项为 offsets
,即索引其偏移量
PUT test_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"index_options": "offsets"
}
}
}
}
向 test_index
索引存储一条数据,该条文本会根据其默认的分词器 standard
分词器将其进行索引
PUT test_index/_doc/1
{
"text": "Quick brown fox"
}
使用全文搜索 match
方法进行搜索,并高亮显示 text
属性,效果如下图,当然如果在Kibana的Discovery中会有高亮显示
GET test_index/_search
{
"query": {
"match": {
"text": "brown fox"
}
},
"highlight": {
"fields": {
"text": {} // text 字段将会被高亮,如下图所示,因为其offsets已经被索引
}
}
}
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-c4eObRkI-1599834691556)(en-resource://database/4294:1)]
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5F9ontJs-1599834691561)(en-resource://database/2639:1)]
PUT test_index
{
"mappings": {
"properties": {
"title":{
"type": "text",
"analyzer": "standard",
"fielddata": true, # 全文类型聚合的话需要开启这个字段
"fields": {
"sort":{
"type": "keyword"
}
},
"index": true,
"search_analyzer": "standard"
}
}
}
}
#插入两条数据,测试一下
PUT test_index/_doc/1
{"title": "York"}
PUT test_index/_doc/2
{"title": "NEW York"}
#查询测试
GET test_index/_search
{
"query": {
"match": {
"title": "york"
}
},
"sort": {
"title.sort": "asc"
}
}
keyword
关键字数据类型
keyword datatype,关键字数据类型,用于索引结构化内容的字段。使用keyword类型的字段,其不会被分析,给什幺值就原封不动地按照这个值索引,所以关键字字段只能按其确切值进行搜索,通常用于过滤、排序和聚合。什幺情况下使用keyword datatype,具有唯一性的字符串,例如:电子邮件地址、MAC地址、身份证号、状态代码…
- eager_global_ordinals:指明该字段是否加载全局序数?默认为false,不加载。 对于经常用于术语聚合的字段,启用此功能是个好主意。
- fields:指明能以不同的方式索引该字段相同的字符串值,例如用于搜索的一个字段和用于排序和聚合的多字段
- ignore_above:不要索引长于此值的任何字符串。默认为2147483647,以便接受所有值
- index:指明该字段是否可以被搜索,默认为true,表示可以被搜索
- index_options:指定该字段应将哪些信息存储在索引中,以便用于评分。默认为docs,但也可以设置为freqs,这样可以在计算分数时考虑术语频率
- norms:在进行查询评分时,是否需要考虑字段长度,默认为false,不考虑
- ignore_above:默认值是256,该参数的意思是,当字段文本的长度大于指定值时,不会被索引,但是会存储。即当字段文本的长度大于指定值时,聚合、全文搜索都查不到这条数据。
ignore_above
最大值是32766
,但是要根据场景来设置,比如说中文最大值
应该是设定在10922
。ignore_above背后的含义:Lucene对一个文本长度进行解析,当这个长度大于32766时,将不会进行analye行为。elasticsearch中采用字符个数来定义ignore_above值,而 Lucene 是采用byte字节。
- 象形文字字符(中文、韩文、日文): 10922 个字符(算法是: 32766 / 3).
- Literal字符(印度问、俄文): 16383 个字符(算法是: 32766 / 2).
- ASCII字符(a-zA-Z0-9以及~!@#$等特殊字符): 32766个字符(算法是: 32766).
PUT test_index
{
"mappings": {
"properties": {
"title":{
"type": "keyword",
"eager_global_ordinals": true,
"fields": {
"sort":{
"type":"text"
}
},
"ignore_above": 1024,
"index": true,
"index_options": "freqs",
"norms": true
}
}
}
}
数字类型
ES支持的数字类型有整型数字类型,integer
类型、long
类型、short
类型、byte
类型。浮点型数字类型 double
类型、 float
类型、 half_float
类型、 scaled_float
类型这类数据类型都是以确切值索引的,可以使用term查询精确匹配。
long
带符号的64位整数,最小值-263,最大值263-1integer
带符号的32位整数,最小值-231,最大值231^-1short
带符号的16位整数,最小值-32768,最大值32767byte
带符号的8位整数,最小值-128,最小值127double
双精度64位IEEE 754 浮点数float
单精度32位IEEE 754 浮点数half_float
半精度16位IEEE 754 浮点数scaled_float
带有缩放因子的缩放类型浮点数,依靠一个long
数字类型通过一个固定的(double
类型)缩放因数进行缩放.
PUT test_index
{
"mappings": {
"properties": {
"number1":{
"type": "long"
},
"number2":{
"type": "integer"
},
"number3":{
"type": "short"
},
"number4":{
"type": "byte"
},
"number5":{
"type": "double"
},
"number6":{
"type": "float"
},
"number7":{
"type": "half_float"
},
"number8":{
"type": "scaled_float",
"scaling_factor": 100 #缩放因子为100,是一个浮点数
}
}
}
}
parameter
- coerce:是否尝试将字符串转换为整数并截断整数的分数,默认为true,接受一个boolean值
- boost:
- doc_values:是否将该字段以逐列的方式存储在磁盘上,用于聚合和排序,默认true
- store:字段是否与
_source
元数据分开存储 - meta:关于字段的元数据,附加到字段上
- ignore_malformed:如果为true,则忽略格式错误的数字;如果为false则格式错误的数字会抛出异常并拒绝整个文档,默认false
- index:指明该字段是否被搜索。默认为true,表示可以被搜索
- null_value:指明一个与该字段相同类型的值去替换掉该字段中的null。默认为null,表示该字段被视为缺失
- scaled_float类型接受一个附加参数
scaling_factor
浮点型数据类型(double、float、half_float),认为-0.0和0.0是不同的值。这意味着在-0.0上进行查询(match or term)匹配不到0.0,反之亦然;范围查询也是如此:如果上限为-0.0则0.0将不匹配,如果下限为0.0则-0.0将不匹配。
整数类型(byte,short,integer和long),要选择满足实际需求的最小类型,这有助于索引和搜索。但请注意:ES存储数据是根据存储的实际值进行优化的,因此选择一种类型而不是另一种类型,将不会影响存储要求。
scaled_float类型需要注意:
scaled_float类型需要格外注意:必须指定缩放因子scaling_factor。
ES索引时,原始值会乘以该缩放因子并四舍五入得到新值,ES内部储存的是这个新值,但返回结果仍是原始值。
例如:scale_factor为10,ES在索引时,的scaled_float字段将在内部存储2.34为23,
查询时,ES都会将查询参数x10再四舍五入得到的值与23匹配,若能匹配到返回结果为2.34
# 先创建一个缩放的索引
PUT test_index?pretty
{
"mappings": {
"properties": {
"scaled_numeric": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
#添加两条数据
#21.2121*100四舍五入得到2121储存结果
#21.2155*100四舍五入得到2122储存结果
POST test_index/_doc
{
"scaled_numeric": 21.2121
}
POST test_index/_doc
{
"scaled_numeric": 21.2155
}
#查询测试
#21.2133*100四舍五入得到2121匹配上面插入的_id=1的数据
#21.2199*100四舍五入得到2122匹配上面插入的_id=2的数据
GET test_index/_search
{
"query": {
"match": {
"number8": 21.2133
}
}
}
GET test_index/_search
{
"query": {
"match": {
"number8": 21.2199
}
}
}
日期类型
日期数据类型。
由于JSON中没有表示日期的数据类型,所以ES中的日期可以表示为:
日期格式化后的字符串,如:”2018-01-01″或”2018/01/01 11:11:11″
long类型值表示自纪元以来的毫秒数
integer类型值表示自纪元以来的秒数
如果指定了时区,ES将日期转换为UTC,然后再存储为自纪元以来的毫秒数(long类型)。
当字段被设置为date类型时,可以自定义日期格式,但如果未指定格式,则使用默认格式:”strict_date_optional_time||epoch_millis”
若未指定自定义日期格式,在保存日期的时候容易出错。若未指定日期格式,ES采用默认日期格式:严格日期格式或者时间戳,
例如:
2020-01-01 —- yes
2020/01/01 —- no
2020-01-1 —- no
1577808000000 —- yes
在使用date类型字段进行排序时,返回的排序值都是以毫秒为单位
parameter
- format:自定义的日期格式,默认:strict_date_optional_time || epoch_millis
- ignore_malformed:若为true,则忽略格式错误的数字;若为false,则格式错误的数字会抛出异常并拒绝整个文档。默认false
- index:指明该字段是否可以被搜索,true为可以,默认true
- null_value:接受其中一个配置格式的日期值作为替换任何显式空值的字段。默认为null,表示该字段被视为缺失
PUT test_index
{
"mappings": {
"properties": {
"date1": {
"type": "date"
},
"date2": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss"
},
"date3": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy/MM/dd||epoch_millis"
}
}
}
}
#添加2条数据
POST test_index/_doc
{
"dateTimeFormat": "2015-01-01 12:10:30"
}
PUT test_index/_doc/1
{
"date1": 1577808000000,
"date2": "2020-01-01 00:00:00",
"date3": "2020/01/01"
}
PUT test_index/_doc/2
{
"date1": 1577808000001,
"date2": "2020-01-01 00:00:01",
"date3": "2020/01/01"
}
#查询测试
GET test_index/_search
{
"sort": [
{
"date2": {
"order": "desc"
}
}
]
}
范围类型
范围数据类型。具有大小关系的一个值区间,所以会用到gt、gte、lt、lte…等逻辑表示符。
ES支持下面6种范围数据类型
integer_range,带符号的32位整数区间,最小值-231,最大值231-1
long_range,带符号的64位整数区间,最小值-263,最小值263-1
float_range,单精度32位IEEE 754浮点数区间
double_range,双精度64位IEEE 754浮点数区间
date_range,日期值范围,表示为系统纪元以来经过的无符号64位整数毫秒
ip_range,支持IPv4或IPv6(或混合)地址ip值范围
PUT test_index
{
"mappings": {
"properties": {
"data1": {
"type": "integer_range"
},
"data2": {
"type": "float_range"
},
"data3": {
"type": "date_range",
"format": "yyyy-MM-dd HH:mm:ss"
},
"data4": {
"type": "ip_range"
}
}
}
}
开始添加数据
PUT test_index/_doc/1
{
"date1": {
"gte": 100,
"lte": 200
},
"date2": {
"gte": 21.21,
"lte": 22
},
"date3": {
"gte": "2020-01-01 00:00:00",
"lte": "2020-01-02 00:00:00"
},
"date4": {
"gte": "192.168.192.10",
"lte": "192.168.192.11"
}
}
查询测试
GET test_index/_search
数组类型
数组类型。默认情况下,任何字段都可以包含零个或多个值,当包含多个值时,它就表示array datatype了。但是,数组中的所有值必须具有相同的数据类型(要幺同为字符串,要幺同为整型,不能数组中一些值为字符串,另一些值为整型)
当数组里面放的是对象(object datatype),即对象数组时,要改为使用nested datatype。
在动态添加字段时,ES从数组中的第一个值确定字段类型,所有后续值必须具有相同的数据类型,或者必须至少可以将后续值强制转换为相同的数据类型。
使用array datatype,不需要预先配置,它们是开箱即用的。(不像整型,它需要手动定义type: “integer”)
使用_mapping查看索引的映射类型时,array datatype不会被写出来,还是以数组的元素的基本类型来表示。
PUT test_index
{
"mappings": {
"properties": {
"data1": {
"type": "long"
},
"data2": {
"type": "text"
}
}
}
}
#添加数据
PUT test_index/_doc/1
{
"date1": [
1,
2,
3
],
"date2": [
"a",
"b",
"c"
]
}
#查询测试
GET test_index/_search
对象类型
即对象类型。一个文档的一个属性可以是一个内部对象,而且,这个内部对象,可以再包含一个内部对象…(可以有多层嵌套)
整个外部文档是一个JSON对象
在ES内部,这种文档会被索引成一种简单平坦的键值对列表(平铺)
PUT test_index
{
"mappings": {
"properties": {
"persion": {
"type": "object"
}
}
}
}
PUT test_index/_doc/1
{
"persion": [
{
"first": "li",
"last": "si"
},
{
"first": "李",
"last": "四"
}
]
}
PUT test_index/_doc/2
{
"persion": [
{
"first": "li",
"last": "四"
},
{
"first": "李",
"last": "si"
}
]
}
#查询测试1
GET test_index/_search
无法做到对象中数组独立索引和查询
#查询测试
GET test_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"persion.first": "li"
}
},
{
"match": {
"persion.last": "si"
}
}
]
}
}
}
出现问题,不正确的匹配。使用nested嵌套对象类型解决
原因:对象类型里的数组类型会将字段平铺为多值字段,因此 li si 之间的关联关系会消失,会将上面的文档转换成如下格式:
{
persion.first:["li 李"]
persion.last:["四 si"]
}
嵌套对象类型
嵌套数据类型,是object datatype的专用版本,在文档属性是一个对象数组时使用,它允许对象数组彼此独立地编制索引和查询
PUT test_index
{
"mappings": {
"properties": {
"persion": {
"type": "nested"
}
}
}
}
#添加数据
PUT test_index/_doc/1
{
"persion": [
{
"first": "li",
"last": "si"
},
{
"first": "李",
"last": "四"
}
]
}
PUT test_index/_doc/2
{
"persion": [
{
"first": "li",
"last": "四"
},
{
"first": "李",
"last": "si"
}
]
}
#查询测试
GET test_index/_search
{
"query": {
"nested": {
"path": "persion",
"query": {
"bool": {
"must": [
{
"match": {
"persion.first": "li"
}
},
{
"match": {
"persion.last": "si"
}
}
]
}
}
}
}
}
地理类型
地址位置数据类型,可以用来表示经纬度。
PUT test_index
{
"mappings": {
"properties": {
"add": {
"type": "geo_point"
}
}
}
}
地理点表示为一个对象,lat属性表示维度,lon属性表示经度
PUT test_index/_doc/1
{
"add": {
"lat": 22.22,
"lon": -22.22
}
}
地理点表示为一个字符串,格式为:”lat,lon”
PUT test_index/_doc/2
{
"add": "22.22,-22.22"
}
地理点表示为一个geohash字符串
PUT test_index/_doc/3
{
"add": "eebnqm5bukpn"
}
地理点表示为一个数组,格式为[lon,lat],注意经纬度顺序字符串标识相反
PUT test_index/_doc/4
{
"add": [
-22.22,
22.22
]
}
参考资料
ignore_above:https://www.jianshu.com/p/4e336b760070