原文链接:https://xiets.blog.csdn.net/article/details/132348634
版权声明:原创文章禁止转载
ES 映射字段的 数据类型,官网文档参考:Field data types。
1. 基本数据类型
下面是 ES 常用的一些基本数据类型。
1.1 字符串
字符串 类型:
keyword
:关键字类型。text
:文本类型。
keyword 类型是不可切分的字符串类型,需要全匹配,用于字符串是否相等的比较。keyword 类型一般用于文档的过滤、排序和聚合。在实际场景用,keyword 一般用于描述 用户名、类型、用户ID、URL 等。
text 类型是可进行分词分隔的字符串类型,支持部分匹配、模糊匹配。由于 text 是模糊匹配,所有支持匹配度打分。text 类型一般用于描述文章标题、文章内容等。
官网相关链接:Keyword type family、Text type family
使用示例:
// 创建索引
PUT /index01
{
"mappings": {
"properties": {
"name": {
"type": "keyword"
},
"desc": {
"type": "text"
}
}
}
}
// 写入文档
PUT /index01/_doc/001
{
"name": "用户名01",
"desc": "这是一位大V用户。"
}
1.2 数值
数值 类型:
long
长整型。integer
:整型。short
:半长整形。byte
:字节类型。float
:浮点型。double
:双精度浮点型。half_float
:半精度浮点型。scaled_float
:可伸缩浮点型。unsigned_long
:无符号长整型。
数值类型支持 相等、范围(大小)比较,也可用于对文档的过滤、排序和聚合。
官网相关链接:Numeric field type
使用示例:
// 创建索引
PUT /index02
{
"mappings": {
"properties": {
"age": {
"type": "integer"
},
"salary": {
"type": "double"
}
}
}
}
// 写入文档
PUT /index02/_doc/001
{
"age": 30,
"salary": 99999.99
}
1.3 布尔
布尔类型:
boolean
:布尔类型。
布尔类型的值只有 true
和 false
两种情况的值。
官网相关链接:Boolean field type
使用示例:
// 创建索引
PUT /index03
{
"mappings": {
"properties": {
"is_male": {
"type": "boolean"
}
}
}
}
// 写入文档
PUT /index03/_doc/001
{
"is_male": true
}
PUT /index03/_doc/002
{
"is_male": false
}
1.4 日期
日期类型:
date
:日期类型。
ES 中存储的日期类型是标准的 UTC 格式。date 类型值的字面表示可以是 格式化的日期时间格式 或 时间戳整数。
date 类型的默认格式为:"strict_date_optional_time||epoch_millis"
。其中 strict_date_optional_time 表示格式化日期时间字符串,例如:“yyyy-MM-dd”、“yyyy-MM-ddTHH:mm:ss”、“yyyy-MM-ddTHH:mm:ssZ”、“yyyyMMdd”、“yyyyMMddHHmmss” 等。epoch_millis 表示自纪元以来的毫秒数(时间戳毫秒数)。
date 类型还可以在索引的 mapping 中设置 format
字段自定义格式。如果自定义格式,则后续写入只支持 format 中自定义的格式。
日期类型支持 相等、范围(大小)比较。
官网相关链接:Date field type
使用示例:
// 创建索引
PUT /index04
{
"mappings": {
"properties": {
"create_time": {
"type": "date" // 使用默认格式
},
"update_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss" // 自定义格式
},
"delete_time": {
"type": "date",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" // 可同时支持多种自定义格式
}
}
}
}
// 写入文档
PUT /index04/_doc/001
{
"create_time": "2023-07-10",
"update_time": "2023-07-10 20:30:30"
}
PUT /index04/_doc/002
{
"create_time": "2015-01-01T12:10:30",
"delete_time": "2023-01-01 00:00:00"
}
PUT /index04/_doc/003
{
"create_time": 1420070400001,
"delete_time": 1420070400001
}
2. 复杂据类型
2.1 数组
ES 数组没有显式的定义方式,基本数据类型的普通字段就可以接收数组类型的值,只需要在写入文档时,把数据用中括号括起来即可。数组字段搜索时也和搜索普通字段一样。
使用示例:
// 创建索引
PUT /book
{
"mappings": {
"properties": {
"tag": { // 声明一个关键字类型的 tag 字段
"type": "keyword"
}
}
}
}
// 写入文档
PUT /book/_doc/001
{
"tag": "编程语言" // 写入字段值
}
PUT /book/_doc/002
{
"tag": ["人工智能", "编程语言"] // 以数组的方式写入值
}
// 查看文档
GET /book/_doc/001
// 返回
{
"_index": "book",
"_id": "001",
"_version": 1,
"_seq_no": 0,
"_primary_term": 1,
"found": true,
"_source": {
"tag": "编程语言"
}
}
GET /book/_doc/002
// 返回
{
"_index": "book",
"_id": "002",
"_version": 1,
"_seq_no": 1,
"_primary_term": 1,
"found": true,
"_source": {
"tag": [
"人工智能",
"编程语言"
]
}
}
// 搜索文档
POST /book/_search
{
"query": {
"term": {
"tag": {
"value": "编程语言"
}
}
}
}
// 返回
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 0.21110919,
"hits": [
{
"_index": "book",
"_id": "001",
"_score": 0.21110919,
"_source": {
"tag": "编程语言"
}
},
{
"_index": "book",
"_id": "002",
"_score": 0.21110919,
"_source": {
"tag": [
"人工智能",
"编程语言"
]
}
}
]
}
}
2.2 对象
对象类型也没有显示的定义方式,也没有指定的 type 类型值,只需要在定义字段的时候,继续给字段加属性即可。
使用示例:
// 创建索引
PUT /topic
{
"mappings": { // 映射
"properties": { // 映射的属性
"title": { // 属性1: keyword类型的 title 字段
"type": "keyword"
},
"content": { // 属性2: text类型的 content 字段
"type": "text"
},
"statistics": { // 属性3: 对象类型的 statistics 字段, 对象有两个属性
"properties": { // 对象的属性
"comment_count": {
"type": "integer"
},
"like_count": {
"type": "integer"
}
}
}
}
}
}
// 写入文档
PUT /topic/_doc/001
{
"title": "主题标题001",
"content": "主题内容001",
"statistics": {
"like_count": 100,
"comment_count": 200
}
}
// 搜索文档
POST /topic/_search
{
"query": {
"range": {
"statistics.like_count": { // 使用 对象.属性 的方式引用属性值
"gte": 100,
"lte": 500
}
}
}
}
// 返回
{
"took": 1,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 1,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "topic",
"_id": "001",
"_score": 1,
"_source": {
"title": "主题标题001",
"content": "主题内容001",
"statistics": {
"like_count": 100,
"comment_count": 200
}
}
}
]
}
}
2.3 地理坐标
ES 支持地理位置坐标和形状区域数据类型的存储和搜索。
其中地理坐标存储了经纬度,可以根据位置距离搜索数据。geo_point
类型表示地理坐标类型。
官网相关链接:
- Geopoint field type:地理坐标类型。
- Geoshape field type:地理形状类型。
geo_point 使用示例:
// 创建索引
PUT /hotel
{
"mappings": {
"properties": {
"title": {
"type": "keyword"
},
"location": { // 地理坐标类型的属性
"type": "geo_point"
}
}
}
}
// 写入文档
PUT /hotel/_doc/001
{
"title": "AAA大酒店",
"location": {
"lat": 22.5369848, // 纬度, 正数表示北纬, 负数表示南纬
"lon": 113.9271766 // 经度, 正数表示东经, 负数表示西经
}
}
PUT /hotel/_doc/002
{
"title": "BBB大酒店",
"location": [113.9174415, 22.5352364] // 以数组的形式写入, 格式: [经度, 纬度]
}
PUT /hotel/_doc/003
{
"title": "CCC大酒店",
"location": "22.5412263,114.0613099" // 以字符串的形式写入, 格式: "纬度,经度"
}
// 根据距离搜索
GET /hotel/_search
{
"query": {
"geo_distance": { // 根据距离搜索
"location": { // 中心点 (指定位置坐标), "location" 是 geo_point 类型的字段名称
"lat": 22.5281343,
"lon": 113.9321684
},
"distance": "5km" // 搜索距离中心点 5km 范围内的酒店
}
}
}
// 返回
{
"took": 3,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"skipped": 0,
"failed": 0
},
"hits": {
"total": {
"value": 2,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "hotel",
"_id": "001",
"_score": 1,
"_source": {
"title": "AAA大酒店",
"location": {
"lat": 22.5369848,
"lon": 113.9271766
}
}
},
{
"_index": "hotel",
"_id": "002",
"_score": 1,
"_source": {
"title": "BBB大酒店",
"location": [
113.9174415,
22.5352364
]
}
}
]
}
}
3. 动态映射
ES 向索引写入文档时,如果相关字段没有在映射中定义,则 ES 会根据写入的数据结构和类型自动扩展映射,这种机制称为动态映射。
动态映射时,JSON 数据类型和索引字段类型的对应关系:
JSON 类型 | ES 索引字段类型 |
---|---|
null | 不增加字段 |
true 或 false | boolean |
interger | long |
float | float |
object | 对象类型 |
array | 根据数组中的第一个非空值决定 |
string | date、double、long、text 都有可能,根据数据格式进行判断 |
通常在创建索引时,最好先把映射字段的数据类型先定义好,因为 ES 的动态映射生成的字段类型可能会与用户的预期有差别。
4. 多类型(子字段)
针对同一个字段,有时可能需要多种数据类型。比如搜索酒店名称时,有时希望分词模糊搜索,有时又希望全匹配搜索,这时就可以把名称定义为 text 类型,然后再增加多一个 keyword 类型的子字段。
使用示例:
// 创建索引
PUT /hotel
{
"mappings": {
"properties": {
"name": { // 字段, 名称为 "name", 类型为 text
"type": "text",
"fields": { // 定义子字段
"keyword_name": { // 子字段, 名称为 "keyword_name", 类型为 keyword
"type": "keyword"
}
}
}
}
}
}
// 写入文档
PUT /hotel/_doc/001
{
"name": "AAA大酒店" // 只需要写入主字段, 会自动应用到子字段
}
PUT /hotel/_doc/002
{
"name": "BBB大酒店"
}
// 搜索文档
POST /hotel/_search
{
"query": {
"match": { // 分词模糊搜索
"name": "酒店"
}
}
}
POST /hotel/_search
{
"query": {
"term": { // 使用子字段全匹配搜索
"name.keyword_name": "AAA大酒店"
}
}
}