本学习笔记基于ElasticSearch 7.10版本,旧版本已经废弃的功能暂时不做笔记,以后有涉及到再做补充。
上一章学习映射的时候,就有接触到一些字段类型。今天来详细说说ElasticSearch中常见的四种字段类型。
一、核心类型
1.1、字符串类型
- string:在es5.0之前,用这个字段来定义字符串,通过index来定义是否需要被分析或者精准查询。但现在,这两种分别被text和keyword类型替代。
- text:使用了这个字段,字段内容就会被分词器分析成一个个词条,相当于之前的analyzed属性。text类型的字段hen不用于排序,很少用于聚合。
- keyword:这种类型适合结构化的字段,用于做精准匹配,例如标签、email 地址、手机号码等等,相当于之前的not-analyzed属性。这种类型的字段可以用作过滤、排序、聚合等。
1.2、数字类型
类型 | 取值范围 |
---|---|
long | -263 ~ 263 |
integer | -231 ~ 231 |
short | -215 ~ 215 |
byte | -27 ~ 27 |
double | 64位的双精度 IEEE754 浮点类型 |
float | 32位的双精度 IEEE754 浮点类型 |
half_float | 16位的双精度 IEEE754 浮点类型 |
scaled_float | 缩放类型的浮点类型 |
- 在满足需求的情况下,优先使用范围小的字段。字段长度越小,索引和搜索的效率越高。
- 浮点数,优先考虑使用scaled_float。例如保存一个价格为99.99的商品,当使用了scaled_float类型,定义比例因子scaling_factor为100,在底层保存的数据就是整数9999,可以提高效率。而在运算时,API还是以浮点类型进行运算。
# 比例因子为100
PUT mapping_demo/_mapping
{
"properties": {
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
1.3、日期类型
JSON中并没有日期类型,所以在es中日期类型可以表现成很多种:
- 日期格式字符串:“2020-12-28"或"2020/12/28 11:11:11”
- 毫秒级别的long类型
- 秒级别的integer类型
不管是什么样的格式,es 内部都会先将时间转为 UTC,然后将时间按照 millseconds-since-the-epoch
来存储成long类型。在查询的时候,再根据字段定义的格式转为字符串输出。
日期类型默认的格式是:strict_date_optional_time||epoch_millis
,可以通过format
属性来自定义日期格式:
PUT mapping_demo/_mapping
{
"properties": {
"datetime": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
1.4、布尔类型
JSON 中的 “true”、“false”、true、false 都可以存储到布尔类型中。
1.5、二进制类型
二进制接受的是 base64 编码的字符串,默认不存储,也不可搜索。
1.6、范围类型
顾名思义,范围类型字段中存储的内容就是一段范围,例如年龄30-55岁,日期在2020-12-28到2021-01-01之间等。
es中有六种范围类型:
- integer_range
- float_range
- long_range
- double_range
- date_range
- ip_range
定义字段时,指定范围类型即可。在插入文档时,需要指定范围的界限:
PUT mapping_demo/_mapping
{
"properties": {
"age_range": {
"type": "integer_range"
}
}
}
# 指定年龄范围,可以使用 gt、gte、lt、lte。
PUT mapping_demo/_doc/3
{
"real_name":"大方哥",
"age_range":{
"gt":20,
"lt":30
}
}
二、复合类型
2.1、数组类型
es中没有专门的数组类型。默认情况下,任何字段都可以有一个或者多个值。需要注意的是,数组中的元素必须是同一种类型。
添加数组时,数组中的第一个元素决定了整个数组的类型。
2.2、对象类型(object)
由于JSON 本身具有层级关系,所以文档包含内部对象。内部对象中,还可以再包含内部对象。
PUT product/_doc/2
{
"date":"2020-11-11T11:11:11Z",
"ext_info":{
"address":"China"
}
}
2.3、嵌套类型(nested)
nested
类型是一种特殊的对象object数据类型specialised version of the object datatype
,允许对象数组彼此独立地进行索引和查询。
Lucene中没有内部对象的概念,所以 es 会将对象层次扁平化,将一个对象转为字段名和值构成的简单列表,例如添加以下文档:
PUT nested/_doc/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
user
会被动态映射为object
类型的,其内部转换成类似下面的文档格式:
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
扁平化处理后,用户名之间的关联关系没有,如果我们使用alice
和white
查询,就会查询出不存在的用户。
如果您需要索引对象数组并保持数组中每个对象的独立性,请使用nested
数据类型,而不是object
数据类型。
PUT nested
{
"mappings": {
"properties": {
"user": {
"type": "nested"
}
}
}
}
在内部,嵌套对象将数组中的每个对象索引为一个单独的隐藏文档,这意味着每个嵌套对象都可以通过查询独立于其他对象进行nested
查询。
使用nested
类型的优缺点:
- 优点:文档存储在一起,读取性能高。
- 缺点:更新父或者子文档时需要更新更个文档。
参考官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/nested.html
三、地理类型
3.1、geo_point
使用场景:
- 查找某一个范围内的地理位置
- 通过地理位置或者相对中心点的距离来聚合文档
- 把距离整合到文档的评分中
- 通过距离对文档进行排序
# 定义geo_point字段类型
PUT people
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
可以通过5种方式来指定一个地理位置:
# object类型指定经纬度
PUT people/_doc/1
{
"text": "Geo-point as an object",
"location": {
"lat": 34.27,
"lon": 108.94
}
}
# 字符串形式指定经纬度,中间用逗号,分隔
PUT people/_doc/2
{
"text": "Geo-point as a string",
"location": "34.27,108.94"
}
# 将经纬度转个Geohash后储存
PUT people/_doc/3
{
"text": "Geo-point as a geohash",
"location": "uzbrgzfxuzup"
}
# 使用数组指定经纬度,注意经度在前,纬度在后
PUT people/_doc/4
{
"text": "Geo-point as an array",
"location": [108.94, 34.27]
}
# 使用WKT原点指定经纬度,注意经度在前,纬度在后
PUT people/_doc/5
{
"text": "Geo-point as a WKT POINT primitive",
"location": "POINT (108.94 34.27)"
}
通过经纬度来指定两左上角top_left
和右下角bottom_rigth
,来查询范围中的位置:
GET people/_search
{
"query": {
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 30,
"lon": 100
},
"bottom_right": {
"lat": 40,
"lon": 110
}
}
}
}
}
geo_point
字段参数:
- ignore_malformed:默认为false,存储格式错误的地理位置将会抛出异常,并且文档也不会写入。true则忽略格式错误的地理位置。
- ignore_z_value:默认为true,接受并存储第三维z轴坐标,但仅索引经纬度。false则指接受二维经纬度,超过二维的地理坐标将会抛出异常。
- null_value:接受null值的地理位置,表示该字段被视为丢失。
3.2、geo_shape
在学习geo_shape
之前,我们先要了解一下GeoJson
。
引用自百度百科:
GeoJSON是一种对各种地理数据结构进行编码的格式,基于Javascript对象表示法(JavaScript Object Notation, 简称JSON)的地理空间信息数据交换格式。GeoJSON对象可以表示几何、特征或者特征集合。GeoJSON支持下面几何类型:点、线、面、多点、多线、多面和几何集合。GeoJSON里的特征包含一个几何对象和其他属性,特征集合表示一系列特征。
es将GeoJson
几何对象都映射到geo_shape
中:
GeoJson | geo_shape | 描述 |
---|---|---|
Point | point | 单个由经纬度描述的地理坐标。注意:Elasticsearch仅使用WGS-84坐标 |
LineString | linestring | 一个任意的线条,由两个以上点组成 |
Polygon | polygon | 一个封闭的多边形,其第一个点和最后一个点必须匹配,由四个以上点组成 |
MultiPoint | multipoint | 一组不连续的点 |
MultiLineString | multilinestring | 多个不关联的线条 |
MultiPolygon | multipolygon | 多个多边形 |
GeometryCollection | geometrycollection | 与JSON形状相似的GeoJSON形状, 可以同时存在多种几何对象类型(例如,Point和LineString)。 |
N/A | envelope | 通过左上角和右下角两个点来指定一个矩形 |
N/A | circle | 由中心点和半径指定的圆 |
# 定义geo_shape字段类型
PUT people
{
"mappings": {
"properties": {
"location": {
"type": "geo_shape"
}
}
}
}
添加地理位置时,需要通过type
指定具体的类型:
# point类型
PUT people/_doc/1
{
"location":{
"type": "point",
"coordinates": [108.94, 34.27]
}
}
# linestring类型
PUT people/_doc/2
{
"location":{
"type": "linestring",
"coordinates": [[108.94, 34.27], [100, 33]]
}
}
# polygon类型
POST /people/_doc/3
{
"location": {
"type": "polygon",
"coordinates": [
[[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]]
]
}
}
...
参考官方文档:
https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-point.html
https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html
四、特殊类型
es中的特殊类型有很多种,下面主要介绍两种最常用的
4.1、ip
顾名思义,这个类型用来存储IP地址:
PUT people
{
"mappings": {
"properties": {
"address": {
"type": "ip"
}
}
}
}
# 通过IPv4添加
PUT people/_doc/1
{
"address":"192.168.1.3"
}
# 查询
GET people/_search
{
"query": {
"term": {
"address": "192.168.0.0/16"
}
}
}
4.2、token_count
token_count
用于统计字符串分词后的词项个数.
# 增加了length字段,用于统计词项个数
PUT blog
{
"mappings": {
"properties": {
"title": {
"type": "text",
"fields": {
"length": {
"type": "token_count",
"analyzer": "standard"
}
}
}
}
}
}
# 添加文档
PUT blog/_doc/1
{
"title": "zhang san"
}
# 使用token_count进行查询
GET blog/_search
{
"query": {
"term": {
"title.length": 2
}
}
}
版权声明:
本文仅记录ElasticSearch学习心得,如有侵权请联系删除。
更多内容请访问原创作者:江南一点雨
版权声明:本文不是「本站」原创文章,版权归原作者所有 | 原文地址: