Elasticsearch-索引设置mappings
前言本文基于elasticsearch7.3.0版本映射是定义文档及其包含的字段如何存储和索引的过程元字段meta-fields元字段用于自定义如何处理与文档相关的元数据,主要包括_source,_index,_type,_id_source_index_type_id字段类型映射参数...
前言
本文基于elasticsearch7.3.0版本
映射是定义文档及其包含的字段如何存储和索引的过程
查看索引mappings
GET index_test/_mapping
元字段meta-fields
元字段用于自定义如何处理与文档相关的元数据,主要包括_source,_index,_type,_id
_source
_source字段存储了在索引时传递的原始JSON文档
_source字段本身没有被索引(因此不是可搜索的),但它被存储起来,以便在执行时可以返回
# 创建索引
PUT index_test
{
"mappings": {
"_source": {
// true,默认值,表示使用_source field
// false,表示禁用,禁用_source field将导致查询时不会返回索引时的原始JSON文档
// 设置成false时注意:虽然字段不存储在_source field中,但是我们仍然可以搜索这个字段
"enabled": true,
// 指定哪些字段保存在_sorce field里面
// 当includes不存在或者存在时数组大小为空,此时存储的字段就是去除excludes之外的字段
// 当includes存在且数组大小不为空,此时存储的字段就是includes指定的字段
"includes": ["field1"],
// 指定哪些字段不保存在_source field里面
"excludes": ["field3"]
},
"properties": {
"field1": {
"type": "keyword"
},
"field2": {
"type": "keyword"
},
"field3": {
"type": "keyword"
}
}
}
}
// includes不存在,excludes中的字段排除掉,所以保存:field1,field2
"_source": {
"excludes": ["field3"]
}
// includes存在但是数组为空,excludes中的字段排除掉,所以保存:field1,field2
"_source": {
"includes": [],
"excludes": ["field3"]
}
// includes存在且数组不为空,保存的字段就是includes指定的字段,所以保存:field1
"_source": {
"includes": ["field1"],
"excludes": ["field3"]
}
_index
表示文档存储在哪个索引中,也可以用来查询和聚合使用
# 聚合每个索引中的文档数
GET _search
{
"size": 0,
"aggs": {
"index_terms_aggs": {
"terms": {
"field": "_index"
}
}
}
}
_type
表示文档存储在索引中的哪个类型里,只有一个类型_doc
_id
文档唯一标识
字段类型
核心数据类型
字符串
- text:索引时会分词,类比查询中的match,查询时会分词
- keyword:索引时不会分词,原样索引,类比查询中的term,查询时不会分词
# 创建索引
PUT index_test
{
"mappings": {
"properties": {
"content":{
// text, 索引时会分词, 可以设置analyzer
"type": "text"
},
"tag":{
// keyword, 索引时不会分词, 不能指定analyzer, 否则创建索引时会报错
"type": "keyword"
}
}
}
}
# 会分词,这里mappings中没有指定analyzer,也没有指定default分析器,所以使用内置standard分析器
POST index_test/_analyze
{
"text":["这是测试文本,测试分词效果"],
"field": "content"
}
# 不会分词
POST index_test/_analyze
{
"text":["这是测试文本,测试分词效果"],
"field": "tag"
}
注意:keyword类型不能设置analyzer,否则创建索引时会报错
# keyword类型指定分析器报错
PUT index_test
{
"mappings": {
"properties": {
"content":{
"type": "text"
},
"tag":{
"type": "keyword",
"analyzer": "ik_max_word"
}
}
}
}
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "Mapping definition for [tag] has unsupported parameters: [analyzer : ik_max_word]"
}
],
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: Mapping definition for [tag] has unsupported parameters: [analyzer : ik_max_word]",
"caused_by": {
"type": "mapper_parsing_exception",
"reason": "Mapping definition for [tag] has unsupported parameters: [analyzer : ik_max_word]"
}
},
"status": 400
}
默认创建的mappings, 每个字符串字段解析成text, 并且会默认一个fields为keyword
// my_test索引事先不存在
POST my_test/_doc/1
{
"userName": "jack",
"password": "123456"
}
// 查看mappings
GET my_test/_mapping
// 结果
{
"my_test" : {
"mappings" : {
"properties" : {
"password" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"userName" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
数字
整数类型
类型 | 取值范围 | 描述 |
---|---|---|
byte | -128 ~ 127(-27 ~ 27-1) | 1个字节,一个有符号的8 bit整数 |
short | -32768 ~ 32767(-215 ~ 215-1) | 2个字节,一个有符号的16 bit整数 |
integer | -231 ~ 231-1 | 4个字节,一个有符号的32 bit整数 |
long | -263 ~ 263-1 | 8个字节,一个有符号的64 bit整数 |
如何选择类型
就整数类型而言(byte, short, integer和long),应该选择适合用例的最小类型。这将有助于索引和搜索效率更高。但是,请注意,存储是基于存储的实际值进行优化的,因此选择一种类型而不是另一种类型将不会对存储需求产生影响。
比如:明确一个值最小值为0,最大为100,选择byte
浮点类型
类型 | 取值范围 |
---|---|
double | 64 bit双精度IEEE 754浮点数 |
float | 32 bit单精度IEEE 754浮点数 |
half_float | 16 bit半精度IEEE 754浮点数 |
scaled_float | 缩放类型的的浮点数,由一个double和一个long型缩放因子组成 |
如何选择类型
对于浮点类型,优先考虑使用带缩放因子的scaled_float浮点类型
如果scaled_float不是很合适,那么你应该在浮点类型中选择适合用例的最小类型:double, float和half_float
对于double、float和half_float,-0.0和+0.0是不同的值,使用term查询查找-0.0不会匹配+0.0,同样range查询中上边界是-0.0不会匹配+0.0,下边界是+0.0不会匹配-0.0。
scaled_float说明:比如价格需要保留三位小数,price为132.889,缩放因子为1000,存起来就是132889
PUT my_test
{
"mappings": {
"properties": {
"price":{
"type": "scaled_float",
// 设置缩放因子,这个参数必须有,否则创建索引时报错
"scaling_factor": 1000
}
}
}
}
PUT my_test/_doc/1
{
// 实际存储的值 : 132.889 * 1000(缩放因子) = 132889
"price": 132.889
}
日期
ElasticSearch 内部会将日期数据转换为UTC,并存储为milliseconds-since-the-epoch的long型整数(时间戳)
详细请参考这篇博客:Elasticsearch-日期数据类型和时区详解
布尔
布尔字段接受JSON true和false值,但也可以接受被解释为true或false的字符串
布尔 | 值 |
---|---|
真 | true, “true” |
假 | false, “false” |
二进制
这个binary类型接受base 64编码的字符串,可用来存储二进制形式的数据
默认情况下,字段只存储不索引,因此也不能被搜索
注意: base 64编码的二进制值必须没有嵌入的换行符。\n
范围
类型 | 取值 |
---|---|
integer_range | 带符号的32 bit整数的范围,-231 ~ 231-1 |
long_range | 有符号64 bit整数的范围,-263 ~ 263-1 |
float_range | 32 bit单精度IEEE 754浮点数范围 |
double_range | 64 bit双精度IEEE 754浮点数范围 |
date_range | 表示milliseconds-since-the-epoch的long型整数, 即64 bit整数毫秒的无符号日期值的范围 |
ip_range | 支持以下任一项的IP值范围IPv 4或IPv 6(或混合)地址 |
PUT range_index
{
"mappings": {
"properties": {
"expected_attendees": {
"type": "integer_range"
},
"time_frame": {
"type": "date_range",
"format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
}
}
}
}
PUT range_index/_doc/1?refresh
{
"expected_attendees" : {
"gte" : 10,
"lte" : 20
},
"time_frame" : {
"gte" : "2015-10-31 12:00:00",
"lte" : "2015-11-01"
}
}
复合数据类型
数组
在Elasticearch中,没有专门的array数据类型。默认情况下,任何字段都可以包含零或多个值,但是数组中的所有值必须具有相同的数据类型,ElasticSearch不支持元素为多个数据类型:[ 10, “some string” ]
数组可能包含null值,这些值要么为配置的null_value或者完全跳过。空数组[]被视为缺失字段–一个没有值的字段
常见数组:
- 字符串数组:[“one”, “two” ]
- 整数数组:[1, 2 ]
- 嵌套数组:[1, [ 2, 3]这相当于[1, 2, 3 ]
- 对象数组:[{ “name”: “Mary”, “age”: 12 }, { “name”: “John”, “age”: 10 }]
注意:对象数组不像预期的那样工作:不能独立于数组中的其他对象查询每个对象。如果您需要能够做到这一点,那么您应该使用nested数据类型,而不是object数据类型。
对象
JSON文档本质上是分层的:文档可能包含内部对象,而内部对象也可能包含内部对象本身
不需要显示的设置字段type为object, 因为这是默认值
# my_index事先不存在
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"
}
# 查看这个索引mappings
GET my_index/_mapping
# 结果
{
"my_index" : {
"mappings" : {
"properties" : {
"manager" : {
"properties" : {
"age" : {
"type" : "long"
},
"name" : {
"properties" : {
"first" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
},
"last" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
},
"region" : {
"type" : "text",
"fields" : {
"keyword" : {
"type" : "keyword",
"ignore_above" : 256
}
}
}
}
}
}
}
对象数组
nested数据类型是一种特殊的object数据类型,它允许对对象数组进行索引,使它们可以彼此独立地查询
object数据类型存在的问题
# my_index索引事先不存在, user字段被动态添加为object字段类型
PUT my_index/_doc/1
{
"group": "fans",
"user": [
{
"first": "John",
"last": "Smith"
},
{
"first": "Alice",
"last": "White"
}
]
}
# 内部存储, user.first和user.last之间没有了关联关系
{
"group" : "fans",
"user.first" : [ "alice", "john" ],
"user.last" : [ "smith", "white" ]
}
# 查询, 此时不能正确地匹配alice AND smith, 本来应该查询不出来数据的, 这时候查询出来了id为1的文档
GET my_index/_search
{
"query": {
"bool": {
"must": [
{
"match": {
"user.first": "Alice"
}
},
{
"match": {
"user.last": "Smith"
}
}
]
}
}
}
如果需要索引对象数组并维护数组中每个对象的独立性,则应使用nested数据类型,而不是object数据类型。在内部,嵌套对象将数组中的每个对象索引为单独的隐藏文档,这意味着每个嵌套对象可以独立于其他对象进行查询,nested查询:
# 创建索引
PUT my_index
{
"mappings": {
"properties": {
"user": {
// 设置字段类型
"type": "nested",
"properties": {
"first": {
"type": "keyword"
},
"last": {
"type": "keyword"
}
}
}
}
}
}
# 索引文档
PUT my_index/_doc/1
{
"group": "fans",
"user": [
{
"first": "John",
"last": "Smith"
},
{
"first": "Alice",
"last": "White"
}
]
}
# 使用nested查询
GET my_index/_search
{
"query": {
"nested": {
"path": "user",
"query": {
"bool": {
// 此查询匹配,因为Alice和White在同一个嵌套对象中
"must": [
{
"match": {
"user.first": "Alice"
}
},
{
"match": {
"user.last": "White"
}
}
]
}
},
// inner_hits允许我们高亮显示匹配的嵌套文档
"inner_hits": {
"highlight": {
"fields": {
"user.first": {}
}
}
}
}
}
}
地理数据类型
地点
类型字段geo_point接受经纬度对
- lat:纬度
- lon:经度
有五种方法可以指定地理点,如下所示:
PUT my_index
{
"mappings": {
"properties": {
"location": {
"type": "geo_point"
}
}
}
}
# 表示为对象的geo_point
PUT my_index/_doc/1
{
"text": "Geo-point as an object",
"location": {
"lat": 41.12,
"lon": -71.34
}
}
# geo_point表示为字符串, 格式为: "lat,lon"(纬度,经度)
PUT my_index/_doc/2
{
"text": "Geo-point as a string",
"location": "41.12,-71.34"
}
# geohash表示geo_point
PUT my_index/_doc/3
{
"text": "Geo-point as a geohash",
"location": "drm3btev3e86"
}
# 数组表示的geo_point, 格式为: [lon, lat]([经度, 纬度])
PUT my_index/_doc/4
{
"text": "Geo-point as an array",
"location": [ -71.34, 41.12 ]
}
# POINT字符串, 存储时报错
# {
# "type": "parse_exception",
# "reason": "unsupported symbol [o] in geohash [POINT(-71.34 41.12)]"
# }
PUT my_index/_doc/5
{
"text": "Geo-point as a WKT POINT primitive",
"location" : "POINT (-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
}
}
}
}
}
地形
这个geo_shape数据类型为任意几何形状(如矩形和多边形)的索引和搜索提供了便利。当要索引的数据或正在执行的查询包含的形状不只是点时,就应该使用它。
可以对类型使用地质形状查询.
特殊数据类型
ip
ip字段可以索引/存储IPv 4或IPv 6地址
completion
这个completion suggester(建议)提供自动完成/搜索即用类型的功能。这是一个导航功能,引导用户在输入时获得相关结果,从而提高搜索精度。它不是用于拼写更正,也不是指像term或phrase suggester。
理想情况下,自动完成功能应该和用户输入一样快,以提供与用户已经输入的内容相关的即时反馈。因此,completion suggester是优化的速度。该建议程序使用的数据结构支持快速查找,但构建成本很高,并且存储在内存中。
token_count
token_count类型是一个integer类型,该字段接受字符串值,对它们进行分析,然后对字符串中的标记数进行索引。
PUT my_index
{
"mappings": {
"properties": {
"name": {
// 使用内置的standard分析器
"type": "text",
"fields": {
"length": {
"type": "token_count",
"analyzer": "standard"
}
}
}
}
}
}
# name分析后有2个token
PUT my_index/_doc/1
{ "name": "John Smith" }
# name分析后有3个token
PUT my_index/_doc/2
{ "name": "Rachel Alice Williams" }
# 查询name包含3个token的文档
GET my_index/_search
{
"query": {
"term": {
"name.length": 3
}
}
}
映射参数
analyzer和search_analyzer
详细参考:Elasticsearch-分析器详解
- analyzer: 指定字段索引和查询时的分析器
- search_analyzer: 指定字段查询时的分析器, 优先级高于analyzer
字段索引时分析器优先级:
- mappings analyzer
- settings default分析器
- 内置standard分析器
字段查询时分析器优先级
- 查询时指定的分析器
- mappings search_analyzer
- mappings analyzer
- settings default_search分析器
- settings default分析器
- 内置standard分析器
format
自定义日期格式化格式
index
index选项控制字段值是否被索引,elasticsearch默认索引所有字段,它接受true或false, 默认为true
没有被索引的字段不可查询, 但是仍然会存储在_source中
enabled
ElasticSearch试图索引给它的所有字段,但有时你只想存储字段而不对其进行索引
这个enabled设置,该设置只能应用于顶层映射定义和object字段,导致Elasticearch完全跳过对字段内容的解析。仍然可以从_source字段,但它不能搜索,也不能存储在store字段中
PUT my_index
{
"mappings": {
"properties": {
"session_data": {
"type": "object",
// 这个session_data字段被禁用
"enabled": false,
// 这个时候store只能为false, 为true则创建索引时报错
"store": false
}
}
}
}
# enabled为false, store为true时, 创建索引报错
{
"error": {
"root_cause": [
{
"type": "mapper_parsing_exception",
"reason": "Mapping definition for [session_data] has unsupported parameters: [store : true]"
}
],
"type": "mapper_parsing_exception",
"reason": "Failed to parse mapping [_doc]: Mapping definition for [session_data] has unsupported parameters: [store : true]",
"caused_by": {
"type": "mapper_parsing_exception",
"reason": "Mapping definition for [session_data] has unsupported parameters: [store : true]"
}
},
"status": 400
}
# 任意数据都可以传递给session_data字段,因为它将被完全忽略
PUT my_index/_doc/session_1
{
"session_data": {
"arbitrary_object": {
"some_array": [ "foo", "bar", { "baz": 2 } ]
}
}
}
# 注意,由于Elasticsearch完全跳过解析字段内容,所以可以将非对象数据添加到禁用的字段中
# 这个session_data也将忽略不是JSON对象的值
PUT my_index/_doc/session_2
{
"session_data": "none"
}
整个映射也可能被禁用,在这种情况下,文档存储在_source字段,这意味着可以检索该字段,但没有以任何方式对其内容进行索引
PUT my_index
{
"mappings": {
// 整个映射被禁用
"enabled": false
}
}
PUT my_index/_doc/session_1
{
"user_id": "kimchy",
"session_data": {
"arbitrary_object": {
"some_array": [ "foo", "bar", { "baz": 2 } ]
}
},
"last_updated": "2015-12-06T18:20:22"
}
# 可以检索文档
GET my_index/_doc/session_1
# 检查映射会发现没有添加任何字段
GET my_index/_mapping
# 返回
{
"my_index" : {
"mappings" : {
"enabled" : false
}
}
}
copy_to
copy_to参数允许你将多个字段的值复制到一组字段中,然后可以将该字段作为单个字段进行查询
PUT my_index
{
"mappings": {
"properties": {
"first_name": {
"type": "text",
"copy_to": "full_name"
},
"last_name": {
"type": "text",
"copy_to": "full_name"
},
"full_name": {
"type": "text",
"store": true
}
}
}
}
PUT my_index/_doc/1
{
"first_name": "John",
"last_name": "Smith"
}
# full_name字段不会出现在_source中
GET my_index/_search
{
"query": {
"match": {
"full_name": {
"query": "John Smith",
"operator": "and"
}
}
}
}
# 返回
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.5753642,
"_source" : {
"first_name" : "John",
"last_name" : "Smith"
}
}
]
}
}
# copy的内容会存储在store字段中
GET my_index/_search
{
"stored_fields": ["full_name"],
"query": {
"match": {
"full_name": {
"query": "John Smith",
"operator": "and"
}
}
}
}
# 返回
{
"took" : 815,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 0.5753642,
"hits" : [
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 0.5753642,
"fields" : {
"full_name" : [
"John",
"Smith"
]
}
}
]
}
}
store
默认情况下,字段值被索引使它们可以被搜索,但它们不是存储,这意味着可以查询字段,但无法检索原始字段值
但通常这不是问题,默认情况下,字段值已经存储在_source里面,所以store默认值为false
如果你只想检索单个字段或几个字段的值,而不是整个_source字段的值。则可以使用source filtering
使用情况一:没有存储在_source中的字段, 可以使用store存储, 比如说:copy_to字段
使用情况二:只想检索指定字段, 通常这个可以使用source filtering代替
store查询和_source查询区别:
- IO的区别: 查询整个_source字段或者_source部分字段都是一次IO, store查询每个字段一次IO, 也就是查询多少个字段就有多少次IO
- 返回值的区别: 查询_source原样返回, 为了保持一致性, 存储的字段总是作为数组返回, 因为无法知道原始字段值是单个值、多个值还是空数组
PUT my_index
{
"mappings": {
"properties": {
"title": {
"type": "text",
"store": true
},
"content": {
"type": "text"
}
}
}
}
PUT my_index/_doc/1
{
"title": "Some short title",
"content": "A very long content field..."
}
# 从store中查询
GET my_index/_search
{
"stored_fields": ["title"]
}
# 返回
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
"fields" : {
// 一个字段一次IO
// 为了保持一致性,存储的字段总是作为数组返回, 因为无法知道原始字段值是单个值、多个值还是空数组
// 如果需要原始值,则应从_source获取字段值
"title" : [
"Some short title"
]
}
}
]
}
}
# 从_source中查询
GET my_index/_search
{
"_source": {
"includes": ["title"]
}
}
# 返回
{
"took" : 0,
"timed_out" : false,
"_shards" : {
"total" : 1,
"successful" : 1,
"skipped" : 0,
"failed" : 0
},
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my_index",
"_type" : "_doc",
"_id" : "1",
"_score" : 1.0,
// 整个_source字段是一次IO
"_source" : {
"title" : "Some short title"
}
}
]
}
}
fields
为了不同的目的,以不同的方式对同一个字段进行索引通常是有用的。这就是multi-fields
例如,字符串可以映射为text字段用于全文搜索,并作为keyword用于排序或聚合的字段
注意:多个字段不会更改_source
PUT my_index
{
"mappings": {
"properties": {
"city": {
"type": "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}
}
PUT my_index/_doc/1
{
"city": "New York"
}
PUT my_index/_doc/2
{
"city": "York"
}
GET my_index/_search
{
"query": {
"match": {
"city": "york"
}
},
"sort": {
"city.raw": "asc"
},
"aggs": {
"Cities": {
"terms": {
"field": "city.raw"
}
}
}
}
multi-fields多分析器
multi-fields的另一个用例是以不同的方式分析同一个字段,以获得更好的相关性。
例如,我们可以用standard分析器将文本分解成文字,然后再用english分析器词根形式
PUT my_index
{
"mappings": {
"properties": {
"text": {
"type": "text",
"fields": {
"english": {
"type": "text",
"analyzer": "english"
}
}
}
}
}
}
PUT my_index/_doc/1
{ "text": "quick brown fox" }
PUT my_index/_doc/2
{ "text": "quick brown foxes" }
GET my_index/_search
{
"query": {
"multi_match": {
"query": "quick brown foxes",
"fields": [
"text",
"text.english"
],
"type": "most_fields"
}
}
}
null_value
null值不能被索引或搜索。当字段设置为null,(空数组[]或数组为null)它被视为该字段没有值
- null_value参数允许你把null显式替换为指定的值,以便可以对其进行索引和搜索
- null_value需要与字段有相同的数据类型。例如,long字段不能指定null_value为字符串
- null_value只影响数据的索引方式,不会修改_source文件
PUT my_index
{
"mappings": {
"properties": {
"status_code": {
"type": "keyword",
// 显式替换为字符串"NULL"
"null_value": "NULL"
}
}
}
}
PUT my_index/_doc/1
{
// 替换
"status_code": null
}
PUT my_index/_doc/2
{
// 空数组不包含显式null,所以不会用null_value
"status_code": []
}
# 查询"NULL", 返回文档1, 不返回文档2
GET my_index/_search
{
"query": {
"term": {
"status_code": "NULL"
}
}
}
doc_values
默认情况下大多数字段都是被索引的,这使得它们可以被搜索。
倒排索引允许查询在唯一排序的term列表中查找搜索词,并从该列表中立即访问包含该term的文档列表。
在脚本中对字段值的排序、聚合和访问需要不同的数据访问模式。
我们不需要查找term和查找文档,而是需要能够查找文档并找到它在某个field中的term。
doc值是在文档索引时构建的磁盘上数据结构,这使得这种数据访问模式成为可能。
它们存储与_source相同的值,但是以一种面向列的方式来进行排序和聚合,效率要高得多。
几乎所有字段类型都支持doc值,除了text和annotated_text字段
默认情况下,所有支持doc值的字段都启用了这些值。
如果你确定不需要对字段进行排序或聚合,或者访问脚本中的字段值,则可以禁用doc值以节省磁盘空间
PUT my_index
{
"mappings": {
"properties": {
"status_code": {
// status_code字段doc_values默认启用
"type": "keyword"
},
"session_id": {
"type": "keyword",
// session_id的doc_values禁用,但仍然可以查询, 不能用于排序和聚合
"doc_values": false
}
}
}
}
更多推荐
所有评论(0)