Elasticsearch (ES) 搜索引擎: 数据类型、动态映射、多类型(子字段)

原文链接:https://xiets.blog.csdn.net/article/details/132348634

版权声明:原创文章禁止转载

专栏目录:Elasticsearch 专栏(总目录)

ES 映射字段的 数据类型,官网文档参考:Field data types

1. 基本数据类型

下面是 ES 常用的一些基本数据类型。

1.1 字符串

字符串 类型:

  • keyword:关键字类型。
  • text:文本类型。

keyword 类型是不可切分的字符串类型,需要全匹配,用于字符串是否相等的比较。keyword 类型一般用于文档的过滤、排序和聚合。在实际场景用,keyword 一般用于描述 用户名、类型、用户ID、URL 等。

text 类型是可进行分词分隔的字符串类型,支持部分匹配、模糊匹配。由于 text 是模糊匹配,所有支持匹配度打分。text 类型一般用于描述文章标题、文章内容等。

官网相关链接:Keyword type familyText 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:布尔类型。

布尔类型的值只有 truefalse 两种情况的值。

官网相关链接: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 类型表示地理坐标类型。

官网相关链接:

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大酒店"
        }
    }
}

猜你喜欢

转载自blog.csdn.net/xietansheng/article/details/132348634