Elasticsearch 字段类型
核心类型
字符串类型
- string : 这是一个已经过期的字符串类型。在 ES 5 之前用这个来描述字符串,现在已经被 text 和 keyword 替代了。
- text : 如果一个字段是要被全文检索的,比如说文章内容,那么可以使用 text。用了 text 之后,字段内容会被分析,在生成倒排索引之前,字符串会被分词器分成一个个的词项,text 类型的字段不用于排序,很少用于聚合。这种字符串也被称之为 analyzed 字段。
- keyword : 这种类型适用于结构化的字段,例如标签、手机号码等等,这种类型的字段可以用作过滤、排序、聚合等。这种字符串也称之为 not-analyzed 字段。
数字类型
类型 | 取值范围 |
---|---|
long | -2^63 到 -2^63-1 |
integer | -2^31 到 -2^31-1 |
short | -2^15 到 -2^15-1 |
byte | -2^7 到 -2^7-1 |
double | 64 位的双精度 IEEE754 浮点类型 |
float | 32 位的双精度 IEEE754 浮点类型 |
half_float | 16 位的双精度 IEEE754 浮点类型 |
scaled_float | 缩放类型的浮点类型 |
在满足需求的情况下,优先使用范围小的字段。字段长度越短,索引和搜索的效率越高。
浮点数,优先考虑使用 scaled_float 。
scaled_float 举例:
1
2
3
4
5
6
7
8
9
10
11
12
13
14PUT product
{
"mappings": {
"properties": {
"name":{
"type": "text"
},
"price":{
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}如上代码,比如我们商品价格精确到分,那么一个88.88元的商品在ES底层存储的为8888,但是由于缩放因子为100,ES给我们提供的所有API返回的为88.88,在底层,long类型比float类型更易压缩存储。
日期类型(date)
由于JSON中没有日期类型,所以ES中的日期类型形式就比较多样。
- 2021-06-09 或者 2021-06-09 11:00:00
- 一个从1970.1.1 零点 到现在的一个秒数或者毫秒数。
ES 内部将时间转为 UTC ,然后将时间按照 millseconds-since-the-epoch 的长整型来存储。
自定义日期类型:
1 | PUT product |
这个能够解析的时间类型比较多。
1 | PUT product/_doc/1 |
上面三个文档中的日期都可以被解析,内部存储的是毫秒计时的长整型数。
布尔类型(boolean)
JSON 中的 “ture”,“false”,true,false。
二进制类型(binary)
二进制接受的是base64编码的字符串,默认不存储,也不可搜索。
范围类型
- integer_range
- float_range
- long_range
- double_range
- date_range
- ip_range
定义的时候,指定范围类型即可。
1 | PUT product |
插入文档时,需要指定文档的界限。
1 | PUT product/_doc/1 |
指定范围时,可以使用gt、gte、lt、lte。
复合类型
数组类型
ES 中没有专门的数组类型。默认情况下,任何字段都可以有一个或多个值。需要注意的是,数组中的元素必须是同一种类型。
添加数组时,数组中的第一个元素就决定了整个数组类型。
对象类型(object)
由于 JSON 本身具有层级关系,所以文档包含内部对象。内部对象中还可以再包含内部对象。
1 | PUT product/_doc/2 |
嵌套类型(nested)
nested 是object 中的一个特例。
如果只使用 object 类型,假如有如下文档:
1 | PUT product/_doc/3 |
由于Luncene 没有内部对象的概念,所以 ES 会将对象层次扁平化,将一个对象转为字段名和值构成的简单列表。即上面的文档最终存储形式如下:
1 | { |
扁平化之后,用户名之间的关系没了。这样会导致如果搜索 Zhang Si 这个人,会搜索到。
此时可以通过nested 类型来解决问题,nested 对象类型可以保持数组中每个对象的独立性。nested 类型 将数组中的每一个对象作为独立隐藏稳定来索引,这样每一个嵌套对象都可以独立被索引。如下结构:
1 | { |
优点:
文档存储1在一起,读取性能高。
缺点:
更新父或者子文档时需要更新整个文档。
地理类型
使用场景:
- 查找某一个范围内的地理位置
- 通过地理位置或者相对中心点的距离来聚合文档
- 把距离整合到文档的评分中
- 通过距离对文档进行排序
geo_point
geo_point 就是一个坐标点。定义方式如下:
1 | PUT people |
创建时指定字段类型,存储时有四种方式。
1 | PUT people/_doc/1 |
注意,使用数组描述时,数组中先经度后纬度。
geo_shape
GeoJSON : https://geojson.org/
GeoJson | Elasticsearch | 备注 |
---|---|---|
Point | point | 一个由经纬度描述的点 |
LineString | linestring | 一个任意的线条,由两个以上的点组成 |
Polygon | polygon | 一个封闭多边形 |
MultiPoint | multipoint | 一组不连续的点 |
MultiLineString | multilinestring | 多条不关联的线 |
MultiPolygon | multipolygon | 多个多边形 |
GeometryCollection | geometrycollection | 几何对象的集合 |
circle | 一个圆形 | |
envelope | 通过左上角和右下角确定的矩形 |
指定 geo_shape 的类型:
1 | PUT people |
添加文档时需要指定具体的类型(点坐标先经度后纬度)。
1 | PUT people/_doc/1 |
如果是linestring,如下:
1 | PUT people/_doc/2 |
特殊类型
IP
存储IP地址,类型是IP。
1 | PUT blog |
1 | PUT blog/_doc/1 |
查询如下:
1 | GET blog/_search |
添加 ipv4,ipv6 地址均可以。
token_count
用于统计字符串分词后的词项个数。
1 | PUT blog |
相当于新增了 title.length 字段用来统计分词后词项的个数。查询方便。
添加文档:
1 | PUT blog/_doc/1 |
可以通过 token_count 去查询。
1 | GET blog/_search |
结果如下:
1 | { |