字段数据类型
elasticsearch 支持文档中字段的许多不同数据类型。
官网:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-types.html
1、核心数据类型
1)String
text(文本数据类型)
例如电子邮件正文或者产品说明。这些字段是 analyzed ,它们通过分析器传递,以在被索引之前将字符串转换为你单个术语的列表。分析过程允许 elasticsearch 搜索单个单词中每个完整的文本字段。文本字段不用于排序,很少用于聚合
示例:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"full_name": {
"type": "text"
}
}
}
}
}
keyword(关键字数据类型)
用于索引结构化内容的字段,例如电子邮件地址,主机名,状态代码,邮政编码或标签。
它们通常用于过滤,排序,和聚合。关键字字段只能按其确切值进行搜索
示例:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"tags": {
"type": "keyword"
}
}
}
}
}
2)Numeric datatypes
long:长整数
integer:整数
short:短整数
byte:字节
double:双精度64位IEEE 754浮点数,限制为有限值
float:单精度32位IEEE 754浮点数,限制为有限值
half_float:半精度16位IEEE 754浮点数,限制为有限值
scaled_float:由a支持的有限浮点数long,由固定double比例因子缩放
示例:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"number_of_bytes": {
"type": "integer"
},
"time_in_seconds": {
"type": "float"
},
"price": {
"type": "scaled_float",
"scaling_factor": 100
}
}
}
}
}
关于使用哪种类型?
至于整数类型(byte,short,integer和long)而言,你应该选择这是足以让你的用例最小的类型。这将有助于索引和搜索更有效。但请注意,存储是根据存储的实际值进行优化的,因此选择一种类型而不是另一种类型将不会影响存储要求。
3)Date datatypes
date:日期
json 没有日期数据类型,因此 Elasticsearch 中的日期可以是:
- 包含格式化日期的字符串,例如 “2015-01-01” 或 “2015/01/01 12:10:30”
- 一个代表毫秒以来的长数字
- 表示自1970年以来的秒数的整数
在内部,日期被转换为 UTC(如果指定了时区)并存储为表示自纪元以来毫秒的长数。
日期查询在内部转换为此长表示的范围查询,聚合和存储字段的结果将转换回字符串,具体取决于与字段关联的日期格式。
日期将始终呈现为字符串,即使它们最初在 JSON 文档中作为long提供
详细日期格式请查看:https://www.elastic.co/guide/en/elasticsearch/reference/current/mapping-date-format.html#strict-date-time
示例:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"date": {
"type": "date"
}
}
}
}
}
4)Boolean datatypes
boolean:true or false
布尔字段接受 JSON true和false值,但也可以接受被解释为true或false的字符串
- false value: false “false”
- true value: true “true”
示例:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"is_published": {
"type": "boolean"
}
}
}
}
}
POST my_index/_doc/1
{
"is_published": "true"
}
GET my_index/_search
{
"query": {
"term": {
"is_published": true
}
}
}
5)Binary datatypes
binary:二进制
该binary 类型接受二进制值作为 Base64 编码的字符串。默认情况下不存储该字段,并且不可搜索,Base64编码的二进制值不得包含嵌入的换行符\n。
示例:
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"name": {
"type": "text"
},
"blob": {
"type": "binary"
}
}
}
}
}
PUT my_index/_doc/1
{
"name": "Some binary blob",
"blob": "U29tZSBiaW5hcnkgYmxvYg=="
}
2、复杂的数据类型
1)Array datatype
array:在 elasticsearch 中,没有专用array类型。默认情况下,任何字段都可以包含零个或多个值,但是,数组中的所有值必须具有相同的数据类型,例如:
- 一个字符串数组:[“one”, “two”]
- 一个整数数组:[1, 2]
- 数组的数组:[1[2, 3]],这个相当于 [1, 2, 3]
- 一个对象数组:[ { “name”: “mary”, “age”: 12}, { “name”: “john”, “age”: 10 } ]
对象数组
对象数组不能像你期望的那样工作:你无法独立于数组中的其他对象查询每个对象。如果你需要能够执行此操作,则应使用 nested 数据类型而不是 object 数据类型。
动态添加字段时,数组中的第一个值确定字段 type。所有后续值必须具有相同的数据类型,或者必须至少可以将后续值强制转换为相同的数据类型。
不支持混合使用数据类型的数组:[ 10, “some string” ]
数组可以包含 null 值,这些值可以由已配置的值替换,也可以 null_value 完全跳过。空数组[]被视为缺失字段,没有值的字段。没有任何东西需要预先配置才能在你文档中使用数组,它们是开箱即用的
PUT my_index/_doc/1
{
"message": "some arrays in this document...",
"tags": [ "elasticsearch", "wow" ], 一
"lists": [ 二
{
"name": "prog_list",
"description": "programming list"
},
{
"name": "cool_list",
"description": "cool stuff list"
}
]
}
PUT my_index/_doc/2 三
{
"message": "no arrays in this document...",
"tags": "elasticsearch",
"lists": {
"name": "prog_list",
"description": "programming list"
}
}
GET my_index/_search
{
"query": {
"match": {
"tags": "elasticsearch" 四
}
}
}
一、该 tags 字段动态添加为 string 字段
二、该 lists 字段作为 object 字段动态添加
三、第二个文档不包含任何数组,但可以索引到相同的字段中
四、查询 elasticsearch 在 tags 字段中查找,并匹配两个文档
多值字段和倒排索引
所有字段类型都支持开箱即用的多值字段,这是 lucene 起源的结果。lucene 旨在成为一个全文搜索引擎。为了能够在大块文本中搜索单个单词,lucene将文本标记为单个术语,并将每个术语分别添加到反向索引中。
这意味着即使是简单的文本字段也必须能够默认支持多个值。当添加其他数据类型(例如数字和日期)时,它们使用与字符串相同的数据结构,因此可以免费获得多值。
2)Object datatype
object:对象数据类型
JSON 文档本质上是分层的:文档可能包含内部对象,而内部对象本身可能包含内部对象
示例:
外部文档也是json对象,它包含一个内部对象manager,其中又包含一个内部对象name
PUT my_index/_doc/1
{
"region": "US",
"manager": {
"age": 30,
"name": {
"first": "John",
"last": "Smith"
}
}
}
在内部,此文档被索引为一个简单,平坦的键值对列表
{
"region": "US",
"manager.age": 30,
"manager.name.first": "John",
"manager.name.last": "Smith"
}
上述文档的显式映射可能如下所示:
映射类型 _doc 是一种对象,并且具有 properties 字段
该 manager 领域是一个内部object领域
该 manager.name 领域是该 object 领域内的内部 manager 领域
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"region": {
"type": "keyword"
},
"manager": {
"properties": {
"age": { "type": "integer" },
"name": {
"properties": {
"first": { "type": "text" },
"last": { "type": "text" }
}
}
}
}
}
}
}
}
3)nested datatype
nested:嵌套数据类型
该 nested 类型是 object 数据类型的专用版本,它允许对象数组可以彼此独立查询的方式编制索引
nested 对象数组,将对象层次结构展平为一个简单的字段名称和值列表,该 user 字段将动态添加为类型字段 object
PUT my_index/_doc/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
在内部转换为看起来更像这样的文档:
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
user.first 和 user.last 字段平面化为多值字段,和之间的关联 alice 和 white 丢失,此文档将错误地匹配查询 alice 和 smith
GET my_index/_search
{
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
使用 nested 对象数组的字段进行
如果需要索引对象数组并保持数组中每个对象的独立性,则应使用 nested 数据类型而不是 object 数据类型。在内部,嵌套对象索引每个对象阵列作为一个单独的隐藏文件中,这意味着每个嵌套对象可以查询独立于其他:
该 user 字段被映射为类型 nested 而不是类型 object
此查询不匹配,因为 alice 并且 smith 不在同一个嵌套对象中
此查询匹配因为 alice 并且 white 位于同一个嵌套对象中。
inner_hits 允许我们突出显示匹配的嵌套文档
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"user": {
"type": "nested"
}
}
}
}
}
PUT my_index/_doc/1
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
GET my_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "Smith" }}
]
}
}
}
}
}
GET my_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
"must": [
{ "match": { "user.first": "Alice" }},
{ "match": { "user.last": "White" }}
]
}
},
"inner_hits": {
"highlight": {
"fields": {
"user.first": {}
}
}
}
}
}
}
3、geo 数据类型
1)Geo-point datatype
geo_point:地理数据类型
geo_point 类型的字段接受纬度/经度,可以使用:
- 在边界框内,在中心点的某个距离内或在多边形内查找地理点
- 通过地理位置或距离中心点的距离来聚合文档
- 将距离整合到文档的相关性分数中
- 按距离对文件进行排序
可以通过四种方式指定地理点:
1、地理点表示为一个对象,带有lat和lon键
2、地理位置表示为字符串,格式为:”lat, lon”
3、geo-point表示为你geohash
4、地理点表示为数组,格式为:[ lon, lat ]
5、一个地理边界框查询,用于查找框内的所有地理点
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
}
PUT my_index/_doc/1
{
"text": "Geo-point as an object",
"location": {
"lat": 41.12,
"lon": -71.34
}
}
PUT my_index/_doc/2
{
"text": "Geo-point as a string",
"location": "41.12,-71.34"
}
PUT my_index/_doc/3
{
"text": "Geo-point as a geohash",
"location": "drm3btev3e86"
}
PUT my_index/_doc/4
{
"text": "Geo-point as an array",
"location": [ -71.34, 41.12 ]
}
GET my_index/_search
{
"query": {
"geo_bounding_box": {
"location": {
"top_left": {
"lat": 42,
"lon": -72
},
"bottom_right": {
"lat": 40,
"lon": -74
}
}
}
}
}
COPY AS CURLVIEW IN CONSOLE
地理点表示为数组或字符串
请注意,字符串地理点的排序方式为 lat、lon。而数组地理点的排序顺序为:lon、lat
最初,lat、lon用于数组和字符串,但数组格式在早期就已更改,以符合 GeoJSON 使用的格式。
2)Geo-shape datatype
https://www.elastic.co/guide/en/elasticsearch/reference/current/geo-shape.html
4、专用数据类型
IP datatype
一个ip字段可以索引/存储任一的ipv4或ipv6的地址,你还可以使用 ip_range 数据类型在单个字段中存储ip范围
PUT my_index
{
"mappings": {
"_doc": {
"properties": {
"ip_addr": {
"type": "ip"
}
}
}
}
}
PUT my_index/_doc/1
{
"ip_addr": "192.168.1.1"
}
GET my_index/_search
{
"query": {
"term": {
"ip_addr": "192.168.0.0/16"
}
}
}
Completion datatype
https://www.elastic.co/guide/en/elasticsearch/reference/current/search-suggesters-completion.html
Token count datatype
https://www.elastic.co/guide/en/elasticsearch/reference/current/token-count.html
mapper-murmur3
https://www.elastic.co/guide/en/elasticsearch/plugins/6.4/mapper-murmur3.html
Percolator type
https://www.elastic.co/guide/en/elasticsearch/reference/current/percolator.html
join datatype
https://www.elastic.co/guide/en/elasticsearch/reference/current/parent-join.html
Alias datatype
https://www.elastic.co/guide/en/elasticsearch/reference/current/alias.html
5、多字段
多字段为不同目的以不同方式索引相同字段通常很有用。例如,string 可以将字段映射为 text 用于全文搜索的 keyword 字段,以及用于排序或聚合的字段。或者,你可以使用 standard、english、french及simple分析器索引文本字段
大多数数据类型都通过 fields 参数支持:https://www.elastic.co/guide/en/elasticsearch/reference/current/multi-fields.html