字段数据类型
edit字段数据类型
edit每个字段都有一个字段数据类型,或字段类型。这个类型指示了字段包含的数据种类,例如字符串或布尔值,以及其预期用途。例如,您可以将字符串索引到text
和keyword
字段中。然而,text
字段值会进行分析以进行全文搜索,而keyword
字符串则保持原样以进行过滤和排序。
字段类型按家族分组。同一家族中的类型具有完全相同的搜索行为,但可能在空间使用或性能特征上有所不同。
目前,有两种类型家族,keyword
和 text
。其他类型家族只有一个字段类型。例如,boolean
类型家族由一个字段类型组成:boolean
。
常见类型
edit对象和关系类型
edit-
object
- 一个JSON对象。
-
flattened
- 一个完整的JSON对象作为一个单一的字段值。
-
nested
- 一个保留其子字段之间关系的JSON对象。
-
join
- 定义同一索引中文档的父子关系。
-
passthrough
- 为同一级别的子字段提供别名。
结构化数据类型
edit聚合数据类型
edit-
aggregate_metric_double
- 预聚合的指标值。
-
histogram
- 以直方图形式预聚合的数值。
文本搜索类型
edit-
text
fields -
文本系列,包括
text
和match_only_text
。 分析过的、非结构化的文本。 -
annotated-text
- 包含特殊标记的文本。用于识别命名实体。
-
completion
- 用于自动完成建议。
-
search_as_you_type
-
text
-类似类型用于 即时完成输入。 -
semantic_text
- 用于执行语义搜索。
-
token_count
- 文本中标记的数量。
文档排名类型
edit-
dense_vector
- 记录浮点值的密集向量。
-
sparse_vector
- 记录稀疏向量的浮点值。
-
rank_feature
- 记录一个数值特征以在查询时提升命中。
-
rank_features
- 记录数值特征以在查询时提升命中率。
空间数据类型
edit其他类型
edit-
percolator
- 索引使用Query DSL编写的查询。
数组
edit在Elasticsearch中,数组不需要专门的字段数据类型。默认情况下,任何字段都可以包含零个或多个值,但是数组中的所有值必须是相同的字段类型。请参阅数组。
多字段
edit对于不同的目的,通常有用的是以不同的方式索引同一个字段。例如,一个字符串
字段可以映射为一个文本
字段用于全文搜索,并且作为一个关键字
字段用于排序或聚合。或者,你可以使用标准
分析器、英语
分析器和法语
分析器来索引一个文本字段。
这就是多字段的目的。大多数字段类型通过fields
参数支持多字段。
聚合指标字段类型
edit存储用于指标聚合的预聚合数值。一个aggregate_metric_double
字段是一个包含一个或多个以下指标子字段的对象:min
、max
、sum
和value_count
。
当您对aggregate_metric_double
字段运行某些指标聚合时,
聚合使用相关子字段的值。例如,对aggregate_metric_double
字段进行
min
聚合将返回所有min
子字段的最小值。
一个 aggregate_metric_double
字段为每个指标子字段存储一个单一的数值
文档值。不支持数组值。min
、max
和 sum
值是 double
数字。value_count
是一个正的 long
数字。
PUT my-index { "mappings": { "properties": { "my-agg-metric-field": { "type": "aggregate_metric_double", "metrics": [ "min", "max", "sum", "value_count" ], "default_metric": "max" } } } }
aggregate_metric_double
字段的参数
edit-
metrics
-
(必需,字符串数组)
要存储的度量子字段的数组。每个值对应一个
度量聚合。有效值为
min
,max
,sum
, 和value_count
。你必须 指定至少一个值。 -
default_metric
-
(必需,字符串)
用于查询、脚本和聚合的默认度量子字段,当这些操作不使用子字段时。必须是从
metrics
数组中取的值。 -
time_series_metric
-
(可选,字符串) 将字段标记为时间序列指标。该值是指标类型。您不能更新现有字段的此参数。
适用于
aggregate_metric_double
字段的有效time_series_metric
值-
gauge
- 表示可以任意增加或减少的单个数值的指标。例如,温度或可用磁盘空间。
-
null
(默认) - 不是时间序列指标。
-
用途
edit我们设计了 aggregate_metric_double
字段,用于以下聚合:
-
一个
min
聚合返回所有min
子字段的最小值。 -
一个
max
聚合返回所有max
子字段的最大值。 -
一个
sum
聚合返回所有sum
子字段值的总和。 -
一个
value_count
聚合返回所有value_count
子字段值的总和。 -
一个
avg
聚合。没有avg
子字段;avg
聚合的结果是使用sum
和value_count
指标计算的。要运行一个avg
聚合,字段必须包含sum
和value_count
指标子字段。
对 aggregate_metric_double
字段运行任何其他聚合将失败,并显示“不支持的聚合”错误。
最后,一个 aggregate_metric_double
字段支持以下查询,它通过将其行为委托给其 default_metric
子字段,表现得像一个 double
:
示例
edit以下创建索引 API 请求创建了一个包含名为 agg_metric
的 aggregate_metric_double
字段的索引。该请求将 max
设置为字段的 default_metric
。
PUT stats-index { "mappings": { "properties": { "agg_metric": { "type": "aggregate_metric_double", "metrics": [ "min", "max", "sum", "value_count" ], "default_metric": "max" } } } }
以下索引 API 请求添加了包含预聚合数据的文档,数据位于 agg_metric
字段中。
PUT stats-index/_doc/1 { "agg_metric": { "min": -302.50, "max": 702.30, "sum": 200.0, "value_count": 25 } } PUT stats-index/_doc/2 { "agg_metric": { "min": -93.00, "max": 1702.30, "sum": 300.00, "value_count": 25 } }
您可以在 agg_metric
字段上运行 min
、max
、sum
、value_count
和 avg
聚合。
POST stats-index/_search?size=0 { "aggs": { "metric_min": { "min": { "field": "agg_metric" } }, "metric_max": { "max": { "field": "agg_metric" } }, "metric_value_count": { "value_count": { "field": "agg_metric" } }, "metric_sum": { "sum": { "field": "agg_metric" } }, "metric_avg": { "avg": { "field": "agg_metric" } } } }
聚合结果基于相关指标子字段的值。
{ ... "aggregations": { "metric_min": { "value": -302.5 }, "metric_max": { "value": 1702.3 }, "metric_value_count": { "value": 50 }, "metric_sum": { "value": 500.0 }, "metric_avg": { "value": 10.0 } } }
对 aggregate_metric_double
字段的查询使用 default_metric
值。
GET stats-index/_search { "query": { "term": { "agg_metric": { "value": 702.30 } } } }
搜索返回了以下结果。default_metric
字段的值,max
,与查询值匹配。
{ ... "hits": { "total": { "value": 1, "relation": "eq" }, "max_score": 1.0, "hits": [ { "_index": "stats-index", "_id": "1", "_score": 1.0, "_source": { "agg_metric": { "min": -302.5, "max": 702.3, "sum": 200.0, "value_count": 25 } } } ] } }
综合 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "agg_metric": { "type": "aggregate_metric_double", "metrics": [ "min", "max", "sum", "value_count" ], "default_metric": "max" } } } } PUT idx/_doc/1 { "agg_metric": { "min": -302.50, "max": 702.30, "sum": 200.0, "value_count": 25 } }
将变为:
{ "agg_metric": { "min": -302.50, "max": 702.30, "sum": 200.0, "value_count": 25 } }
别名字段类型
edit一个 alias
映射定义了索引中字段的替代名称。
该别名可以在 搜索 请求中代替目标字段使用,
并且可以在其他一些API中使用,例如 字段能力。
PUT trips { "mappings": { "properties": { "distance": { "type": "long" }, "route_length_miles": { "type": "alias", "path": "distance" }, "transit_mode": { "type": "keyword" } } } } GET _search { "query": { "range" : { "route_length_miles" : { "gte" : 39 } } } }
几乎所有搜索请求的组件都接受字段别名。特别是,别名可以用于查询、聚合、排序字段,以及在请求docvalue_fields
、stored_fields
、建议和高亮时使用。脚本在访问字段值时也支持别名。请参阅不支持的API部分了解例外情况。
在搜索请求的某些部分以及请求字段能力时,可以提供字段通配符模式。在这些情况下,通配符模式将匹配字段别名以及具体字段:
GET trips/_field_caps?fields=route_*,transit_mode
别名目标
edit关于别名的目标有一些限制:
- 目标必须是一个具体字段,而不是对象或其他字段别名。
- 目标字段必须在创建别名时存在。
- 如果定义了嵌套对象,字段别名必须与其目标具有相同的嵌套范围。
此外,字段别名只能有一个目标。这意味着不能在单个子句中使用字段别名来查询多个目标字段。
可以通过映射更新将别名更改为引用新的目标。已知的一个限制是,如果任何存储的percolator查询包含该字段别名,它们仍将引用其原始目标。更多信息可以在percolator文档中找到。
不支持的API
edit不支持写入字段别名:尝试在索引或更新请求中使用别名将导致失败。同样,别名不能用作copy_to
的目标或在多字段中使用。
因为别名在文档源中不存在,所以在执行源过滤时不能使用别名。例如,以下请求将为_source
返回空结果:
GET /_search { "query" : { "match_all": {} }, "_source": "route_length_miles" }
目前只有搜索和字段能力API可以接受并解析字段别名。 其他接受字段名称的API,例如term vectors,不能与字段别名一起使用。
最后,一些查询,如terms
、geo_shape
和more_like_this
,允许从索引文档中获取查询信息。由于在获取文档时不支持字段别名,因此指定查找路径的部分查询不能通过别名引用字段。
数组
edit在Elasticsearch中,没有专门的数组
数据类型。默认情况下,任何字段都可以包含零个或多个值,但是数组中的所有值必须具有相同的数据类型。例如:
-
一个字符串数组:[
"one"
,"two"
] -
一个整数数组:[
1
,2
] -
一个数组的数组:[
1
, [2
,3
]] 等同于 [1
,2
,3
] -
一个对象数组:[
{ "name": "Mary", "age": 12 }
,{ "name": "John", "age": 10 }
]
当动态添加字段时,数组中的第一个值决定了字段的类型
。所有后续值必须具有相同的数据类型,或者至少可以将后续值强制转换为相同的数据类型。
混合数据类型的数组不支持:[ 10
, "some string"
]
数组可能包含 null
值,这些值要么被配置的 null_value
替换,要么完全跳过。一个空数组 []
被视为缺失字段——一个没有值的字段。
在文档中使用数组无需预先配置,它们是开箱即用的:
PUT my-index-000001/_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-000001/_doc/2 { "message": "no arrays in this document...", "tags": "elasticsearch", "lists": { "name": "prog_list", "description": "programming list" } } GET my-index-000001/_search { "query": { "match": { "tags": "elasticsearch" } } }
二进制字段类型
editThe binary
type accepts a binary value as a
Base64 encoded string. The field is not
stored by default and is not searchable:
PUT my-index-000001 { "mappings": { "properties": { "name": { "type": "text" }, "blob": { "type": "binary" } } } } PUT my-index-000001/_doc/1 { "name": "Some binary blob", "blob": "U29tZSBiaW5hcnkgYmxvYg==" }
binary
字段的参数
edit以下参数被binary
字段接受:
该字段是否应以列步长的方式存储在磁盘上,以便以后可以用于排序、聚合或脚本编写?接受 |
|
字段值是否应与 |
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
合成源可能会按照字节表示的顺序对二进制
值进行排序。例如:
PUT idx { "mappings": { "_source": { "mode": "synthetic" }, "properties": { "binary": { "type": "binary", "doc_values": true } } } } PUT idx/_doc/1 { "binary": ["IAA=", "EAA="] }
将变为:
{ "binary": ["EAA=", "IAA="] }
布尔字段类型
edit布尔字段接受 JSON true
和 false
值,但也可以接受被解释为真或假的字符串:
假值 |
|
真值 |
|
例如:
PUT my-index-000001 { "mappings": { "properties": { "is_published": { "type": "boolean" } } } } POST my-index-000001/_doc/1?refresh { "is_published": "true" } GET my-index-000001/_search { "query": { "term": { "is_published": true } } }
聚合操作,如terms
聚合,使用1
和0
作为key
,以及字符串"true"
和
"false"
作为key_as_string
。布尔字段在脚本中使用时,
返回true
和false
:
POST my-index-000001/_doc/1?refresh { "is_published": true } POST my-index-000001/_doc/2?refresh { "is_published": false } GET my-index-000001/_search { "aggs": { "publish_state": { "terms": { "field": "is_published" } } }, "sort": [ "is_published" ], "fields": [ {"field": "weight"} ], "runtime_mappings": { "weight": { "type": "long", "script": "emit(doc['is_published'].value ? 10 : 0)" } } }
布尔字段的参数
edit以下参数被boolean
字段接受:
字段是否应以列步长的方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受 |
|
字段是否应快速可搜索?接受 |
|
尝试将错误的数据类型索引到字段中会默认抛出异常,并拒绝整个文档。如果此参数设置为true,则允许忽略该异常。格式错误的字段不会被索引,但文档中的其他字段会正常处理。接受 |
|
接受上述任何真或假值。该值将替换任何显式的 |
|
|
定义如果在索引时由 |
|
如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档上为此字段设置了值,则文档将被拒绝并显示错误。 脚本的格式与其运行时等效项相同。 |
字段值是否应与 |
|
字段的元数据。 |
|
|
(可选, 布尔值) 将字段标记为时间序列维度。默认为
维度字段具有以下约束:
|
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
布尔
字段在其默认配置中支持 synthetic _source
。
合成源可以对布尔
字段值进行排序。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "bool": { "type": "boolean" } } } } PUT idx/_doc/1 { "bool": [true, false, true, false] }
将变为:
{ "bool": [false, false, true, true] }
完成字段类型
edit要使用completion
suggester,请将您希望从中生成建议的字段映射为类型completion
。这将索引字段值以实现快速完成。
PUT music { "mappings": { "properties": { "suggest": { "type": "completion" } } } }
用于completion
字段的参数
edit以下参数由 completion
字段接受:
要使用的索引分析器,默认为 |
|
要使用的搜索分析器,默认为 |
|
|
保留分隔符,默认为 |
|
启用位置增量,默认为 |
|
限制单个输入的长度,默认为 |
日期字段类型
editJSON 没有日期数据类型,因此在 Elasticsearch 中的日期可以是:
-
包含格式化日期的字符串,例如
"2015-01-01"
或"2015/01/01 12:10:30"
。 - 表示自纪元以来的毫秒数的数字。
- 表示自纪元以来的秒数的数字(配置)。
在内部,日期会被转换为UTC(如果指定了时区),并以表示自纪元以来的毫秒数的长数字形式存储。
如果需要纳秒级分辨率,请使用date_nanos字段类型。
日期查询在内部被转换为对此长整型表示的范围查询,并且聚合和存储字段的结果根据与字段关联的日期格式转换回字符串。
日期将始终以字符串形式呈现,即使它们最初在JSON文档中是以长整型提供的。
日期格式可以自定义,但如果未指定format
,则使用默认格式:
"strict_date_optional_time||epoch_millis"
这意味着它将接受带有可选时间戳的日期,这些日期符合strict_date_optional_time
或自纪元以来的毫秒数所支持的格式。
例如:
PUT my-index-000001 { "mappings": { "properties": { "date": { "type": "date" } } } } PUT my-index-000001/_doc/1 { "date": "2015-01-01" } PUT my-index-000001/_doc/2 { "date": "2015-01-01T12:10:30Z" } PUT my-index-000001/_doc/3 { "date": 1420070400001 } GET my-index-000001/_search { "sort": { "date": "asc"} }
日期
将接受带有小数点的数字,如 {"date": 1618249875.123456}
但在某些情况下(#70085),我们会丢失这些日期的精度,因此应避免使用。
多种日期格式
edit可以通过使用 ||
作为分隔符来指定多种格式。
每种格式将依次尝试,直到找到匹配的格式。第一个格式将用于将 自纪元以来的毫秒数 值转换回字符串。
PUT my-index-000001 { "mappings": { "properties": { "date": { "type": "date", "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis" } } } }
date
字段的参数
edit以下参数被date
字段接受:
字段是否应以列步长的方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受 |
|
可以解析的日期格式。默认为
|
|
|
用于解析日期时的区域设置,因为不同语言中月份的名称和/或缩写不同。默认值为英语。 |
如果 |
|
该字段是否应快速可搜索?接受 |
|
接受以配置的 |
|
|
定义如果在索引时由 |
|
如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源读取值。如果在输入文档上为此字段设置了值,则文档将被拒绝并返回错误。脚本的格式与其运行时等效相同,并且应发出长值时间戳。 |
字段值是否应与 |
|
字段的元数据。 |
纪元秒
edit如果你需要将日期发送为自纪元以来的秒数,请确保format
列表中包含epoch_second
:
PUT my-index-000001 { "mappings": { "properties": { "date": { "type": "date", "format": "strict_date_optional_time||epoch_second" } } } } PUT my-index-000001/_doc/example?refresh { "date": 1618321898 } POST my-index-000001/_search { "fields": [ {"field": "date"}], "_source": false }
这将回复一个类似以下的日期:
{ "hits": { "hits": [ { "_id": "example", "_index": "my-index-000001", "_score": 1.0, "fields": { "date": ["2021-04-13T13:51:38.000Z"] } } ] } }
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
合成源可能会对日期
字段值进行排序。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "date": { "type": "date" } } } } PUT idx/_doc/1 { "date": ["2015-01-01T12:10:30Z", "2014-01-01T12:10:30Z"] }
将变为:
{ "date": ["2014-01-01T12:10:30.000Z", "2015-01-01T12:10:30.000Z"] }
日期纳秒字段类型
edit此数据类型是对 date
数据类型的补充。然而,两者之间有一个重要的区别。现有的 date
数据类型以毫秒分辨率存储日期。而 date_nanos
数据类型以纳秒分辨率存储日期,这限制了其日期范围大约从 1970 年到 2262 年,因为日期仍然存储为自纪元以来的纳秒数的长整型表示。
对纳秒的查询在内部被转换为对此长整型表示的范围查询,并且聚合和存储字段的结果根据与该字段关联的日期格式转换回字符串。
日期格式可以自定义,但如果未指定format
,则使用默认格式:
"strict_date_optional_time_nanos||epoch_millis"
例如:
PUT my-index-000001 { "mappings": { "properties": { "date": { "type": "date_nanos" } } } } PUT my-index-000001/_bulk?refresh { "index" : { "_id" : "1" } } { "date": "2015-01-01" } { "index" : { "_id" : "2" } } { "date": "2015-01-01T12:10:30.123456789Z" } { "index" : { "_id" : "3" } } { "date": 1420070400000 } GET my-index-000001/_search { "sort": { "date": "asc"}, "runtime_mappings": { "date_has_nanos": { "type": "boolean", "script": "emit(doc['date'].value.nano != 0)" } }, "fields": [ { "field": "date", "format": "strict_date_optional_time_nanos" }, { "field": "date_has_nanos" } ] }
The |
|
本文档使用一个简单的日期。 |
|
本文档包含一个时间。 |
|
本文档使用自纪元以来的毫秒数。 |
|
请注意,返回的 |
|
在脚本中使用 |
|
您可以在使用 |
您还可以指定多个日期格式,用||
分隔。与date
字段相同的映射参数也可以使用。
日期纳秒
将接受带有小数点的数字,如 {"date": 1618249875.123456}
但在某些情况下(#70085),我们会丢失这些日期的精度,因此应避免使用。
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
合成源可能会对 date_nanos
字段值进行排序。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "date": { "type": "date_nanos" } } } } PUT idx/_doc/1 { "date": ["2015-01-01T12:10:30.000Z", "2014-01-01T12:10:30.000Z"] }
将变为:
{ "date": ["2014-01-01T12:10:30.000Z", "2015-01-01T12:10:30.000Z"] }
密集向量字段类型
editThe dense_vector
字段类型存储数值的密集向量。密集向量字段主要用于 k-nearest neighbor (kNN) search。
The dense_vector
类型不支持聚合或排序。
您添加一个 dense_vector
字段作为基于 element_type
的数值数组,默认情况下使用 float
:
PUT my-index { "mappings": { "properties": { "my_vector": { "type": "dense_vector", "dims": 3 }, "my_text" : { "type" : "keyword" } } } } PUT my-index/_doc/1 { "my_text" : "text1", "my_vector" : [0.5, 10, 6] } PUT my-index/_doc/2 { "my_text" : "text2", "my_vector" : [-0.5, 10, 10] }
与大多数其他数据类型不同,密集向量始终是单值的。
无法在一个dense_vector
字段中存储多个值。
用于kNN搜索的索引向量
edit一个k近邻(kNN)搜索找到与查询向量最接近的k个向量,通过相似性度量来衡量。
密集向量场可以用于在script_score
查询中对文档进行排序。这使您可以通过扫描所有文档并根据相似性对它们进行排序来执行暴力kNN搜索。
在许多情况下,暴力kNN搜索效率不够高。因此,dense_vector
类型支持将向量索引到一种特殊的数据结构中,以通过搜索API中的knn
选项支持快速kNN检索。
大小在128到4096之间的未映射浮点数组字段会动态映射为dense_vector
,默认相似度为cosine
。
您可以通过显式地将字段映射为dense_vector
并指定所需的相似度来覆盖默认相似度。
默认情况下,密集向量字段启用索引,并被索引为int8_hnsw
。
当启用索引时,您可以在kNN搜索中定义要使用的向量相似度:
PUT my-index-2 { "mappings": { "properties": { "my_vector": { "type": "dense_vector", "dims": 3, "similarity": "dot_product" } } } }
对向量进行索引以进行近似kNN搜索是一个昂贵的过程。对于包含启用了index
的向量字段的文档,摄取这些文档可能需要大量时间。请参阅k-最近邻(kNN)搜索以了解更多关于内存需求的信息。
您可以通过将 index
参数设置为 false
来禁用索引:
PUT my-index-2 { "mappings": { "properties": { "my_vector": { "type": "dense_vector", "dims": 3, "index": false } } } }
Elasticsearch 使用 HNSW 算法 来支持高效的 kNN 搜索。与大多数 kNN 算法一样,HNSW 是一种近似方法,它牺牲了结果的准确性以提高速度。
自动量化向量以进行kNN搜索
editThe dense_vector
type supports quantization to reduce the memory footprint required when searching float
vectors.
The three following quantization strategies are supported:
+
int8
- 将向量的每个维度量化为1字节整数。这会以一定的精度为代价,将内存占用减少75%(或4倍)。
int4
- 将向量的每个维度量化为半字节整数。这会以一定的精度为代价,将内存占用减少87%(或8倍)。
bbq
-
[预览]
此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic将努力修复任何问题,但技术预览中的功能不受官方GA功能支持SLA的约束。
更好的二进制量化,将每个维度减少到单个比特精度。这会以更大的精度为代价,将内存占用减少96%(或32倍)。通常,在查询期间进行过采样和重新排序可以帮助缓解精度损失。
在使用量化格式时,您可能希望对结果进行过采样和重新评分以提高准确性。有关更多信息,请参阅过采样和重新评分。
要使用量化索引,您可以将索引类型设置为int8_hnsw
、int4_hnsw
或bbq_hnsw
。当索引float
向量时,当前默认的索引类型是int8_hnsw
。
量化将继续在磁盘上保留原始浮点向量值,以便在数据的生命周期内进行重新排序、重新索引和量化改进。
这意味着由于存储量化和原始向量的开销,磁盘使用量将增加约25%用于int8
,约12.5%用于int4
,以及约3.1%用于bbq
。
int4
量化需要偶数维的向量。
[预览]
此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
bbq
量化仅支持大于 64 的向量维度。
这里是一个如何创建字节量化索引的示例:
PUT my-byte-quantized-index { "mappings": { "properties": { "my_vector": { "type": "dense_vector", "dims": 3, "index": true, "index_options": { "type": "int8_hnsw" } } } } }
这是一个如何创建半字节量化索引的示例:
PUT my-byte-quantized-index { "mappings": { "properties": { "my_vector": { "type": "dense_vector", "dims": 4, "index": true, "index_options": { "type": "int4_hnsw" } } } } }
[预览] 此功能处于技术预览阶段,可能会在未来的版本中进行更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。 以下是如何创建二进制量化索引的示例:
PUT my-byte-quantized-index { "mappings": { "properties": { "my_vector": { "type": "dense_vector", "dims": 64, "index": true, "index_options": { "type": "bbq_hnsw" } } } } }
密集向量字段的参数
edit接受的映射参数如下:
有效的element_type
值
-
float
- 为每个维度索引一个4字节的浮点值。这是默认值。
-
byte
- 为每个维度索引一个1字节整数值。
-
bit
-
为每个维度索引一个单独的位。适用于非常高维的向量或特别支持位向量的模型。
注意:当使用
bit
时,维度的数量必须是8的倍数,并且必须表示位数。
-
dims
-
(可选,整数)
向量的维度数量。不能超过
4096
。如果未指定dims
,则将设置为添加到该字段中的第一个向量的长度。 -
index
-
(可选, 布尔值)
如果为
true
,您可以使用kNN搜索API来搜索此字段。默认为true
。
-
similarity
-
(可选*, 字符串)
用于kNN搜索的向量相似度度量。文档根据其向量字段与查询向量的相似度进行排序。每个文档的
_score
将根据相似度得出,以确保分数为正且分数越大表示排名越高。 当element_type: bit
时,默认值为l2_norm
,否则默认值为cosine
。
bit
向量仅支持 l2_norm
作为它们的相似度度量。
+
* 当 index
为 true
时,才能指定此参数。
+
. similarity
的有效值
详情
-
l2_norm
-
基于向量之间的L2距离(也称为欧几里得距离)计算相似度。文档的
_score
计算公式为1 / (1 + l2_norm(query, vector)^2)
。
对于bit
向量,不使用l2_norm
,而是使用向量之间的hamming
距离。_score
的转换公式为(numBits - hamming(a, b)) / numBits
-
dot_product
-
计算两个单位向量的点积。此选项提供了一种优化的方式来执行余弦相似度。约束条件和计算的分数由
element_type
定义。当
element_type
为float
时,所有向量必须为单位长度,包括文档和查询向量。文档的_score
计算公式为(1 + dot_product(query, vector)) / 2
。当
element_type
为byte
时,所有向量必须具有相同的长度,包括文档向量和查询向量,否则结果将不准确。 文档的_score
计算公式为0.5 + (dot_product(query, vector) / (32768 * dims))
其中dims
是每个向量的维度数。 -
cosine
-
计算余弦相似度。在索引期间,Elasticsearch 会自动将使用
cosine
相似度的向量归一化为单位长度。这使得内部可以使用dot_product
来计算相似度,从而提高效率。原始的未归一化向量仍然可以通过脚本访问。文档的_score
计算为(1 + cosine(query, vector)) / 2
。cosine
相似度不允许零幅值的向量,因为在这种情况下余弦未定义。 -
max_inner_product
-
计算两个向量的最大内积。这类似于
dot_product
,但不要求向量归一化。这意味着每个向量的幅度可以显著影响分数。文档的_score
被调整以防止负值。对于max_inner_product
值< 0
,_score
为1 / (1 + -1 * max_inner_product(query, vector))
。对于非负的max_inner_product
结果,_score
计算为max_inner_product(query, vector) + 1
。
尽管它们在概念上相关,但similarity
参数与text
字段的similarity
不同,并接受一组不同的选项。
-
index_options
-
(可选*,对象) 一个可选的部分,用于配置kNN索引算法。HNSW算法有两个内部参数,影响数据结构的构建方式。可以调整这些参数以提高结果的准确性,但会牺牲索引速度。
* 当
index
为true
时,才能指定此参数。Properties of
index_options
-
type
-
(必需,字符串) 要使用的kNN算法的类型。可以是以下任意一种:
-
hnsw
- 这利用了HNSW算法进行可扩展的近似kNN搜索。这支持所有element_type
值。 -
int8_hnsw
- 浮点向量的默认索引类型。 这利用了HNSW算法,并自动进行标量量化,以实现可扩展的近似kNN搜索,element_type
为float
。这可以减少4倍的内存占用,但会牺牲一些准确性。参见自动量化向量以进行kNN搜索。 -
int4_hnsw
- 这利用了HNSW算法,并自动进行标量量化,以实现可扩展的近似kNN搜索,element_type
为float
。这可以减少8倍的内存占用,但会牺牲一些准确性。参见自动量化向量以进行kNN搜索。 -
[preview]
此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic将努力修复任何问题,但技术预览版中的功能不受官方GA功能的SLA支持。
bbq_hnsw
- 这利用了HNSW算法,并自动进行二进制量化,以实现可扩展的近似kNN搜索,element_type
为float
。这可以减少32倍的内存占用,但会牺牲准确性。参见自动量化向量以进行kNN搜索。 -
flat
- 这利用了暴力搜索算法进行精确的kNN搜索。这支持所有element_type
值。 -
int8_flat
- 这利用了暴力搜索算法,并自动进行标量量化。仅支持element_type
为float
。 -
int4_flat
- 这利用了暴力搜索算法,并自动进行半字节标量量化。仅支持element_type
为float
。 -
[preview]
此功能处于技术预览阶段,可能会在未来的版本中更改或删除。Elastic将努力修复任何问题,但技术预览版中的功能不受官方GA功能的SLA支持。
bbq_flat
- 这利用了暴力搜索算法,并自动进行二进制量化。仅支持element_type
为float
。
-
-
m
-
(可选,整数)
HNSW图中每个节点将连接的邻居数量。
默认为
16
。仅适用于hnsw
、int8_hnsw
和int4_hnsw
索引类型。 -
ef_construction
-
(可选,整数)
在为每个新节点组装最近邻居列表时跟踪的候选者数量。默认为
100
。仅适用于hnsw
、int8_hnsw
和int4_hnsw
索引类型。 -
confidence_interval
-
(可选,浮点数)
仅适用于
int8_hnsw
、int4_hnsw
、int8_flat
和int4_flat
索引类型。量化向量时使用的置信区间。 可以是0.90
到1.0
之间的任何值,包括0.90
和1.0
,或正好是0
。当值为0
时,表示应为优化量化计算动态分位数。当值在0.90
和1.0
之间时,此值限制了计算量化阈值时使用的值。 例如,值为0.95
时,仅使用中间95%的值来计算量化阈值(例如,最高和最低2.5%的值将被忽略)。 默认为int8
量化向量的1/(dims + 1)
和int4
的0
用于动态分位数计算。
-
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
dense_vector
字段支持 合成 _source
。
索引与搜索位向量
edit当使用element_type: bit
时,这将把所有向量视为位向量。位向量每个维度仅使用一个位,并在内部编码为字节。这对于非常高维的向量或模型非常有用。
当使用bit
时,维度的数量必须是8的倍数,并且必须表示位数。此外,使用bit
向量时,典型的向量相似性值实际上都被评分相同,例如使用hamming
距离。
让我们比较两个 byte[]
数组,每个数组代表40个单独的位。
[-127, 0, 1, 42, 127]
以位表示为 1000000100000000000000010010101001111111
[127, -127, 0, 1, 42]
以位表示为 0111111110000001000000000000000100101010
在比较这两个位向量时,我们首先计算汉明
距离。
xor
结果:
1000000100000000000000010010101001111111 ^ 0111111110000001000000000000000100101010 = 1111111010000001000000010010101101010101
然后,我们计算xor
结果中1
位的数量:18
。为了进行评分缩放,我们从总位数中减去并除以总位数:(40 - 18) / 40 = 0.55
。这将是这两个向量之间的_score
。
这是一个关于位向量索引和搜索的示例:
PUT my-bit-vectors { "mappings": { "properties": { "my_vector": { "type": "dense_vector", "dims": 40, "element_type": "bit" } } } }
POST /my-bit-vectors/_bulk?refresh {"index": {"_id" : "1"}} {"my_vector": [127, -127, 0, 1, 42]} {"index": {"_id" : "2"}} {"my_vector": "8100012a7f"}
然后,在搜索时,您可以使用 knn
查询来搜索相似的位向量:
POST /my-bit-vectors/_search?filter_path=hits.hits { "query": { "knn": { "query_vector": [127, -127, 0, 1, 42], "field": "my_vector" } } }
{ "hits": { "hits": [ { "_index": "my-bit-vectors", "_id": "1", "_score": 1.0, "_source": { "my_vector": [ 127, -127, 0, 1, 42 ] } }, { "_index": "my-bit-vectors", "_id": "2", "_score": 0.55, "_source": { "my_vector": "8100012a7f" } } ] } }
可更新的字段类型
edit为了更好地适应扩展和性能需求,可以使用更新映射API来更新index_options
中的type
设置,如下图所示(允许跳跃):
flat --> int8_flat --> int4_flat --> hnsw --> int8_hnsw --> int4_hnsw
对于更新所有HNSW类型(hnsw
、int8_hnsw
、int4_hnsw
),连接数m
必须保持不变或增加。对于标量量化格式(int8_flat
、int4_flat
、int8_hnsw
、int4_hnsw
),confidence_interval
必须始终保持一致(一旦定义,不能更改)。
在所有其他情况下,更新 index_options
中的 type
将会失败。
切换类型
不会重新索引已经索引的向量(它们将继续使用其原始类型
),更改后索引的向量将使用新的类型
。
例如,可以定义一个密集向量字段,该字段利用flat
类型(原始float32数组)来索引第一批数据。
PUT my-index-000001 { "mappings": { "properties": { "text_embedding": { "type": "dense_vector", "dims": 384, "index_options": { "type": "flat" } } } } }
将type
更改为int4_hnsw
可以确保更改后索引的向量将使用int4标量量化表示和HNSW(例如,用于KNN查询)。
这包括由合并先前创建的段而创建的新段。
PUT /my-index-000001/_mapping { "properties": { "text_embedding": { "type": "dense_vector", "dims": 384, "index_options": { "type": "int4_hnsw" } } } }
在此更改之前索引的向量将继续使用flat
类型(原始float32表示和用于KNN查询的暴力搜索)。
为了将所有向量更新为新类型,应使用重新索引或强制合并。
为了调试目的,可以使用索引段API检查每个类型
存在多少个段(和文档)。
展平字段类型
edit默认情况下,对象中的每个子字段都会分别进行映射和索引。如果子字段的名称或类型不是预先知道的,那么它们会动态映射。
The flattened
类型提供了一种替代方法,其中整个对象被映射为一个单一字段。给定一个对象,flattened
映射将解析其叶子值,并将它们作为关键字索引到一个字段中。然后可以通过简单的查询和聚合来搜索对象的内容。
这种数据类型对于索引具有大量或未知数量唯一键的对象非常有用。整个JSON对象只创建一个字段映射,这有助于防止因过多不同字段映射而导致的映射爆炸。
另一方面,扁平化的对象字段在搜索功能方面存在一定的权衡。仅允许基本查询,不支持数值范围查询或高亮显示。有关限制的更多信息,请参阅支持的操作部分。
不应使用 flattened
映射类型来索引所有文档内容,因为它将所有值视为关键词,并且不提供完整的搜索功能。默认方法,即每个子字段在映射中都有自己的条目,在大多数情况下都能很好地工作。
可以按如下方式创建一个扁平化的对象字段:
PUT bug_reports { "mappings": { "properties": { "title": { "type": "text" }, "labels": { "type": "flattened" } } } } POST bug_reports/_doc/1 { "title": "Results are not sorted correctly.", "labels": { "priority": "urgent", "release": ["v1.2.5", "v1.3.0"], "timestamp": { "created": 1541458026, "closed": 1541457010 } } }
在索引过程中,会为JSON对象中的每个叶子值创建标记。这些值被索引为字符串关键字,不进行分析或对数字或日期进行特殊处理。
查询顶层的 flattened
字段会搜索对象中的所有叶子值:
POST bug_reports/_search { "query": { "term": {"labels": "urgent"} } }
要在扁平化对象中查询特定键,使用对象点表示法:
POST bug_reports/_search { "query": { "term": {"labels.release": "v1.3.0"} } }
支持的操作
edit由于值的索引方式相似,flattened
字段与 keyword
字段在映射和搜索功能上有很多相似之处。
目前,扁平化对象字段可以用于以下查询类型:
-
term
,terms
, 和terms_set
-
prefix
-
range
-
match
和multi_match
-
query_string
和simple_query_string
-
exists
在查询时,无法使用通配符引用字段键,例如
{ "term": {"labels.time*": 1541457010}}
。请注意,所有查询,包括
range
,都将值视为字符串关键字。在
flattened
字段上不支持高亮显示。
可以对展平的对象字段进行排序,并执行简单的关键字风格聚合,例如 terms
。与查询一样,没有对数值的特殊支持——JSON 对象中的所有值都被视为关键字。在排序时,这意味着值是按字典顺序进行比较的。
目前无法存储扁平化的对象字段。无法在映射中指定store
参数。
检索扁平化字段
edit可以使用fields参数检索字段值和具体子字段。由于flattened
字段将整个对象映射为单个字段,因此响应包含来自_source
的未修改结构。
然而,单个子字段可以通过在请求中明确指定它们来获取。 这仅适用于具体路径,但不能使用通配符:
PUT my-index-000001 { "mappings": { "properties": { "flattened_field": { "type": "flattened" } } } } PUT my-index-000001/_doc/1?refresh=true { "flattened_field" : { "subfield" : "value" } } POST my-index-000001/_search { "fields": ["flattened_field.subfield"], "_source": false }
{ "took": 2, "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-000001", "_id": "1", "_score": 1.0, "fields": { "flattened_field.subfield" : [ "value" ] } }] } }
您还可以使用Painless脚本从扁平化字段的子字段中检索值。在您的Painless脚本中,使用doc['
而不是doc['
。例如,如果您有一个名为label
的扁平化字段,并且它有一个release
子字段,您的Painless脚本将是doc['labels.release'].value
。
例如,假设您的映射包含两个字段,其中一个字段的类型是flattened
:
PUT my-index-000001 { "mappings": { "properties": { "title": { "type": "text" }, "labels": { "type": "flattened" } } } }
索引一些包含映射字段的文档。labels
字段有三个子字段:
POST /my-index-000001/_bulk?refresh {"index":{}} {"title":"Something really urgent","labels":{"priority":"urgent","release":["v1.2.5","v1.3.0"],"timestamp":{"created":1541458026,"closed":1541457010}}} {"index":{}} {"title":"Somewhat less urgent","labels":{"priority":"high","release":["v1.3.0"],"timestamp":{"created":1541458026,"closed":1541457010}}} {"index":{}} {"title":"Not urgent","labels":{"priority":"low","release":["v1.2.0"],"timestamp":{"created":1541458026,"closed":1541457010}}}
因为 labels
是一个 flattened
字段类型,整个对象被映射为一个单一字段。要在 Painless 脚本中从这个子字段中检索值,请使用 doc['
格式。
"script": { "source": """ if (doc['labels.release'].value.equals('v1.3.0')) {emit(doc['labels.release'].value)} else{emit('Version mismatch')} """
扁平化对象字段的参数
edit接受的映射参数如下:
|
展平对象字段允许的最大深度,以嵌套内部对象的形式表示。如果展平对象字段超过此限制,则会抛出错误。默认值为 |
字段是否应以列步长的方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受 |
|
是否应在刷新时急切加载全局序数?接受 |
|
超过此限制的叶子值将不会被索引。默认情况下,没有限制,所有值都会被索引。请注意,此限制适用于扁平化对象字段中的叶子值,而不是整个字段的长度。 |
|
确定字段是否应可搜索。接受 |
|
在评分目的中,索引中应存储哪些信息。默认值为 |
|
一个字符串值,用于替换扁平化对象字段中任何显式的 |
|
使用哪种评分算法或相似度。默认为 |
|
|
是否应在为此字段构建查询时,将全文查询的输入在空白处拆分。接受 |
|
(可选,字符串数组) 扁平化对象内的字段列表,其中每个字段是时间序列的一个维度。每个字段使用从根字段开始的相对路径指定,并且不包括根字段名称。 |
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
扁平化字段在其默认配置中支持合成 `_source`。
合成源可能会对扁平化
字段值进行排序并去除重复项。
例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "flattened": { "type": "flattened" } } } } PUT idx/_doc/1 { "flattened": { "field": [ "apple", "apple", "banana", "avocado", "10", "200", "AVOCADO", "Banana", "Tangerine" ] } }
将变为:
{ "flattened": { "field": [ "10", "200", "AVOCADO", "Banana", "Tangerine", "apple", "avocado", "banana" ] } }
合成源始终使用嵌套对象而不是对象数组。 例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "flattened": { "type": "flattened" } } } } PUT idx/_doc/1 { "flattened": { "field": [ { "id": 1, "name": "foo" }, { "id": 2, "name": "bar" }, { "id": 3, "name": "baz" } ] } }
将变为(注意嵌套对象而不是“扁平化”数组):
{ "flattened": { "field": { "id": [ "1", "2", "3" ], "name": [ "bar", "baz", "foo" ] } } }
合成源始终对单元素数组使用单值字段。 例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "flattened": { "type": "flattened" } } } } PUT idx/_doc/1 { "flattened": { "field": [ "foo" ] } }
将变为(注意嵌套对象而不是“扁平化”数组):
{ "flattened": { "field": "foo" } }
地理点字段类型
edit类型为 geo_point
的字段接受纬度-经度对,这些可以用于:
与geo_shape和point一样,geo_point
可以在GeoJSON
和Well-Known Text格式中指定。
然而,出于方便和历史原因,还支持许多其他格式。
总共有六种方式可以指定一个地理点,如下所示:
PUT my-index-000001 { "mappings": { "properties": { "location": { "type": "geo_point" } } } } PUT my-index-000001/_doc/1 { "text": "Geopoint as an object using GeoJSON format", "location": { "type": "Point", "coordinates": [-71.34, 41.12] } } PUT my-index-000001/_doc/2 { "text": "Geopoint as a WKT POINT primitive", "location" : "POINT (-71.34 41.12)" } PUT my-index-000001/_doc/3 { "text": "Geopoint as an object with 'lat' and 'lon' keys", "location": { "lat": 41.12, "lon": -71.34 } } PUT my-index-000001/_doc/4 { "text": "Geopoint as an array", "location": [ -71.34, 41.12 ] } PUT my-index-000001/_doc/5 { "text": "Geopoint as a string", "location": "41.12,-71.34" } PUT my-index-000001/_doc/6 { "text": "Geopoint as a geohash", "location": "drm3btev3e86" } GET my-index-000001/_search { "query": { "geo_bounding_box": { "location": { "top_left": { "lat": 42, "lon": -72 }, "bottom_right": { "lat": 40, "lon": -74 } } } } }
以对象形式表示的地理点,采用GeoJSON格式,包含 |
|
以Well-Known Text表示的地理点
格式为: |
|
以对象表示的地理点,包含 |
|
地理点表示为一个数组,格式为:[ |
|
以字符串形式表示的地理点,格式为: |
|
以geohash表示的地理点。 |
|
一个地理边界框查询,用于查找所有位于该框内的地理点。 |
以数组或字符串表示的地理点
请注意,字符串地理点按 纬度,经度
顺序排列,而数组地理点、GeoJSON 和 WKT 则按相反顺序排列:经度,纬度
。
这一现象的原因是历史性的。地理学家传统上先写纬度
,再写经度
,而最近为地理数据指定的格式,如GeoJSON和Well-Known Text,则先写经度
,再写纬度
(东距在前,北距在后),以符合数学上先写x
再写y
的惯例。
geo_point
字段的参数
edit以下参数被geo_point
字段接受:
如果 |
|
|
如果为 |
字段是否应快速可搜索?接受 |
|
接受一个地理点值,该值将替换任何显式的 |
|
|
定义如果在索引时由 |
|
如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档上为此字段设置了值,则文档将被拒绝并返回错误。 脚本格式与其运行时等效相同,并且应发出一对(lat, lon)双精度值。 |
在脚本中使用地理点
edit当在脚本中访问地理点的值时,该值将返回为一个GeoPoint
对象,从而可以分别访问.lat
和.lon
值:
def geopoint = doc['location'].value; def lat = geopoint.lat; def lon = geopoint.lon;
出于性能原因,直接访问纬度/经度值会更好:
def lat = doc['location'].lat; def lon = doc['location'].lon;
合成源
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
合成源可能会对geo_point
字段进行排序(先按纬度,再按经度),并将它们减少到存储的精度。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "point": { "type": "geo_point" } } } } PUT idx/_doc/1 { "point": [ {"lat":-90, "lon":-80}, {"lat":10, "lon":30} ] }
将变为:
{ "point": [ {"lat":-90.0, "lon":-80.00000000931323}, {"lat":9.999999990686774, "lon":29.999999972060323} ] }
地理形状字段类型
editThe geo_shape
数据类型有助于索引和搜索任意地理形状,如矩形、线和多边形。如果被索引的数据包含的形状不仅仅是点,则需要使用此映射。如果数据仅包含点,则可以将其索引为 geo_point
或 geo_shape
。
使用此类型的文档可以用于:
-
查找范围内的地理形状:
- 一个 边界框
- 某个中心点的 距离
-
一个
geo_shape
查询(例如,相交的多边形)。
-
按地理网格聚合文档:
映射选项
editThe geo_shape
mapping maps GeoJSON or WKT geometry objects to the geo_shape
type. 要启用它,用户必须显式地将字段映射到 geo_shape
类型。
Option | Description | Default |
---|---|---|
|
可选。字段的WKT多边形的默认方向。 此参数设置并返回仅一个 要设置
要设置
|
|
|
如果为真,格式错误的GeoJSON或WKT形状将被忽略。如果为假(默认),格式错误的GeoJSON和WKT形状将抛出异常并拒绝整个文档。 |
|
|
如果为 |
|
|
如果 |
|
|
字段是否应该快速可搜索?接受 |
|
|
字段是否应以列步长的方式存储在磁盘上,以便以后可以用于聚合或脚本编写? |
|
索引方法
editGeoshape 类型通过将形状分解为三角网格并 将每个三角形索引为 BKD 树中的一个 7 维点来进行索引。这提供了 接近完美的空间分辨率(精度可达 1e-7 小数度),因为所有 空间关系都是使用原始形状的编码向量表示来计算的。镶嵌器的主要性能 主要取决于定义多边形/多边形的顶点数量。
示例
editPUT /example { "mappings": { "properties": { "location": { "type": "geo_shape" } } } }
输入结构
edit形状可以使用GeoJSON 或熟知文本 (WKT)格式表示。下表提供了GeoJSON和WKT到Elasticsearch类型的映射:
GeoJSON Type | WKT Type | Elasticsearch Type | Description |
---|---|---|---|
|
|
|
一个地理坐标。注意:Elasticsearch仅使用WGS-84坐标。 |
|
|
|
给定两个或更多点的一条任意线。 |
|
|
|
一个闭合的多边形,其第一个和最后一个点必须匹配,因此需要 |
|
|
|
一组未连接但可能相关的点。 |
|
|
|
一组独立的线串。 |
|
|
|
一个由多个独立多边形组成的数组。 |
|
|
|
一个类似于 |
|
|
|
一个边界矩形,或信封,通过仅指定左上角和右下角点来指定。 |
对于所有类型,type
和 coordinates
字段都是必需的。
点是一个单一的地理坐标,例如建筑物的位置或智能手机的Geolocation API提供的当前位置。以下是GeoJSON中一个点的示例。
POST /example/_doc { "location" : { "type" : "Point", "coordinates" : [-77.03653, 38.897676] } }
以下是一个WKT中点的示例:
POST /example/_doc { "location" : "POINT (-77.03653 38.897676)" }
由两个或更多位置组成的数组定义的线串。通过仅指定两个点,线串将表示一条直线。指定两个以上的点将创建任意路径。以下是GeoJSON中线串的一个示例。
POST /example/_doc { "location" : { "type" : "LineString", "coordinates" : [[-77.03653, 38.897676], [-77.009051, 38.889939]] } }
以下是WKT中一个线串的示例:
POST /example/_doc { "location" : "LINESTRING (-77.03653 38.897676, -77.009051 38.889939)" }
上述线字符串将从白宫开始绘制一条直线到美国国会大厦。
多边形由一系列点列表定义。每个(外部)列表中的第一个和最后一个点必须是相同的(多边形必须是封闭的)。以下是GeoJSON中多边形的一个示例。
POST /example/_doc { "location" : { "type" : "Polygon", "coordinates" : [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ] ] } }
以下是WKT中多边形的一个示例:
POST /example/_doc { "location" : "POLYGON ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0))" }
第一个数组表示多边形的外边界,其他数组表示内部形状(“孔”)。以下是一个带有孔的多边形的GeoJSON示例:
POST /example/_doc { "location" : { "type" : "Polygon", "coordinates" : [ [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0] ], [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2] ] ] } }
以下是一个带有孔洞的多边形的WKT示例:
POST /example/_doc { "location" : "POLYGON ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8, 100.2 0.2))" }
多边形方向
edit多边形的方向表示其顶点的顺序:RIGHT
(逆时针)或LEFT
(顺时针)。Elasticsearch使用多边形的方向来确定它是否跨越国际日期变更线(+/-180°经度)。
您可以使用orientation
映射参数为WKT多边形设置默认方向。这是因为WKT规范没有指定或强制默认方向。
GeoJSON 多边形使用默认的 RIGHT
方向,无论 orientation
映射参数的值如何。这是因为 GeoJSON 规范 规定外多边形使用逆时针方向,而内部形状使用顺时针方向。
您可以使用文档级别的 orientation
参数覆盖GeoJSON多边形的默认方向。例如,以下索引请求指定了一个文档级别的 orientation
为 LEFT
。
POST /example/_doc { "location" : { "type" : "Polygon", "orientation" : "LEFT", "coordinates" : [ [ [-177.0, 10.0], [176.0, 15.0], [172.0, 0.0], [176.0, -15.0], [-177.0, -10.0], [-177.0, 10.0] ] ] } }
Elasticsearch 仅使用多边形的方向来确定它是否穿越国际日期变更线。如果多边形的最小经度和最大经度之间的差异小于180°,则该多边形不会穿越日期变更线,其方向没有影响。
如果一个多边形的最小经度和最大经度之间的差值为180°或更大,Elasticsearch会检查该多边形的文档级orientation
是否与默认方向不同。如果方向不同,Elasticsearch会认为该多边形跨越了国际日期变更线,并在日期变更线处将多边形分割。
以下是GeoJSON点列表的一个示例:
POST /example/_doc { "location" : { "type" : "MultiPoint", "coordinates" : [ [102.0, 2.0], [103.0, 2.0] ] } }
以下是一个WKT点列表的示例:
POST /example/_doc { "location" : "MULTIPOINT (102.0 2.0, 103.0 2.0)" }
以下是一个GeoJSON线串列表的示例:
POST /example/_doc { "location" : { "type" : "MultiLineString", "coordinates" : [ [ [102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0] ], [ [100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0] ], [ [100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8] ] ] } }
以下是WKT线串列表的一个示例:
POST /example/_doc { "location" : "MULTILINESTRING ((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0), (100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8))" }
以下是一个包含GeoJSON多边形列表的示例(第二个多边形包含一个洞):
POST /example/_doc { "location" : { "type" : "MultiPolygon", "coordinates" : [ [ [[102.0, 2.0], [103.0, 2.0], [103.0, 3.0], [102.0, 3.0], [102.0, 2.0]] ], [ [[100.0, 0.0], [101.0, 0.0], [101.0, 1.0], [100.0, 1.0], [100.0, 0.0]], [[100.2, 0.2], [100.8, 0.2], [100.8, 0.8], [100.2, 0.8], [100.2, 0.2]] ] ] } }
以下是一个WKT多边形列表的示例(第二个多边形包含一个洞):
POST /example/_doc { "location" : "MULTIPOLYGON (((102.0 2.0, 103.0 2.0, 103.0 3.0, 102.0 3.0, 102.0 2.0)), ((100.0 0.0, 101.0 0.0, 101.0 1.0, 100.0 1.0, 100.0 0.0), (100.2 0.2, 100.8 0.2, 100.8 0.8, 100.2 0.8, 100.2 0.2)))" }
以下是一个包含多个GeoJSON几何对象的示例:
POST /example/_doc { "location" : { "type": "GeometryCollection", "geometries": [ { "type": "Point", "coordinates": [100.0, 0.0] }, { "type": "LineString", "coordinates": [ [101.0, 0.0], [102.0, 1.0] ] } ] } }
以下是一个WKT几何对象集合的示例:
POST /example/_doc { "location" : "GEOMETRYCOLLECTION (POINT (100.0 0.0), LINESTRING (101.0 0.0, 102.0 1.0))" }
信封
editElasticsearch 支持一种 envelope
类型,它由形状的左上角和右下角的坐标组成,以表示边界矩形,格式为 [[minLon, maxLat], [maxLon, minLat]]
:
POST /example/_doc { "location" : { "type" : "envelope", "coordinates" : [ [100.0, 1.0], [101.0, 0.0] ] } }
以下是使用WKT BBOX格式的信封示例:
注意: WKT 规范要求以下顺序:minLon, maxLon, maxLat, minLat。
POST /example/_doc { "location" : "BBOX (100.0, 102.0, 2.0, 0.0)" }
圆形
editGeoJSON 和 WKT 都不支持点-半径圆类型。相反,使用圆摄取处理器将圆近似为多边形
。
排序和检索索引形状
edit由于形状的复杂输入结构和索引表示,目前无法直接对形状进行排序或检索其字段。geo_shape
值只能通过 _source
字段检索。
合成源
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
直方图字段类型
edit用于存储表示直方图的预聚合数值数据的字段。 此数据使用两个配对数组定义:
因为values
数组中的元素与count
数组中相同位置的元素相对应,所以这两个数组必须具有相同的长度。
-
一个
直方图
字段每个文档只能存储一对值
和计数
数组。不支持嵌套数组。 -
直方图
字段不支持排序。
用途
edithistogram
字段主要用于聚合。为了使其更易于用于聚合,histogram
字段数据存储为二进制 doc values 而不是索引。其大小(以字节为单位)最多为 13 * numValues
,其中 numValues
是提供的数组的长度。
由于数据未被索引,您只能将 histogram
字段用于以下聚合和查询:
构建直方图
edit在使用直方图作为聚合的一部分时,结果的准确性将取决于直方图的构建方式。考虑用于构建直方图的分位数聚合模式非常重要。一些可能性包括:
-
对于T-Digest模式,
values
数组表示平均质心位置,而counts
数组表示归属于每个质心的值的数量。如果算法已经开始近似百分位数,这种不准确性会在直方图中延续。 -
对于高动态范围 (HDR)直方图模式,
values
数组表示每个桶区间的固定上限,而counts
数组表示归属于每个区间的值的数量。此实现保持固定的最坏情况百分比误差(以有效数字的数量指定),因此在生成直方图时使用的值将是您在聚合时可以实现的最大精度。
直方图字段是“算法无关”的,并且不存储特定于T-Digest或HDRHistogram的数据。虽然这意味着该字段在技术上可以使用任一算法进行聚合,但实际上用户应选择一种算法并以该方式索引数据(例如,T-Digest的质心或HDRHistogram的区间),以确保最佳准确性。
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
直方图
字段支持在其默认配置中使用 合成 _source
。
为了节省空间,直方图文档值中不存储零计数的桶。因此,当在启用了合成源的索引中索引直方图字段时,索引包含零计数桶的直方图将导致在获取直方图时缺少桶。
示例
edit以下创建索引 API 请求创建了一个包含两个字段映射的新索引:
-
my_histogram
,一个用于存储百分位数据的histogram
字段 -
my_text
,一个用于存储直方图标题的keyword
字段
PUT my-index-000001 { "mappings" : { "properties" : { "my_histogram" : { "type" : "histogram" }, "my_text" : { "type" : "keyword" } } } }
以下索引 API 请求存储了两个直方图的预聚合数据:histogram_1
和 histogram_2
。
PUT my-index-000001/_doc/1 { "my_text" : "histogram_1", "my_histogram" : { "values" : [0.1, 0.2, 0.3, 0.4, 0.5], "counts" : [3, 7, 23, 12, 6] } } PUT my-index-000001/_doc/2 { "my_text" : "histogram_2", "my_histogram" : { "values" : [0.1, 0.25, 0.35, 0.4, 0.45, 0.5], "counts" : [8, 17, 8, 7, 6, 2] } }
每个桶的值。数组中的值被视为双精度数,并且必须按递增顺序给出。对于T-Digest直方图,此值表示平均值。在HDR直方图的情况下,这表示迭代到的值。 |
|
每个桶的计数。数组中的值被视为长整数,并且必须为正数或零。负值将被拒绝。桶与计数之间的关系由数组中的位置给出。 |
IP 字段类型
editPUT my-index-000001 { "mappings": { "properties": { "ip_addr": { "type": "ip" } } } } PUT my-index-000001/_doc/1 { "ip_addr": "192.168.1.1" } GET my-index-000001/_search { "query": { "term": { "ip_addr": "192.168.0.0/16" } } }
您还可以使用 ip_range 数据类型 在单个字段中存储 IP 范围。
ip
字段的参数
edit以下参数由 ip
字段接受:
-
doc_values
-
字段是否应以列步长方式存储在磁盘上,以便以后可以用于排序、聚合或脚本编写?接受
true
(默认)或false
。 -
ignore_malformed
-
如果
true
,格式错误的IP地址将被忽略。如果false
(默认),格式错误的IP地址将抛出异常并拒绝整个文档。请注意,如果使用了script
参数,则无法设置此项。 -
index
-
字段是否应快速可搜索?接受
true
(默认)和false
。仅启用了doc_values
的字段仍然可以使用术语或基于范围的查询进行查询, 尽管速度较慢。 -
null_value
-
接受一个IPv4或IPv6值,该值将替换任何显式的
null
值。 默认为null
,这意味着该字段被视为缺失。请注意,如果使用了script
参数,则不能设置此项。 -
on_script_error
-
定义如果在索引时由
script
参数定义的脚本抛出错误时该怎么办。接受reject
(默认),这将导致整个文档被拒绝,以及ignore
,这将把字段注册在文档的_ignored
元数据字段中并继续索引。此参数只能在设置了script
字段时设置。 -
script
- 如果设置此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档中为此字段设置了值,则文档将被拒绝并返回错误。 脚本格式与其运行时等效相同,并且应发出包含IPv4或IPv6格式地址的字符串。
-
store
-
字段值是否应与
_source
字段分开存储和检索。接受true
或false
(默认)。 -
time_series_dimension
-
(可选,布尔值)
将字段标记为时间序列维度。默认为
false
。索引设置
index.mapping.dimension_fields.limit
限制了索引中的维度数量。维度字段具有以下约束:
-
doc_values
和index
映射参数必须为true
。
-
查询 ip
字段
edit查询 IP 地址最常见的方式是使用
CIDR
表示法:[ip_address]/[prefix_length]
。例如:
GET my-index-000001/_search { "query": { "term": { "ip_addr": "192.168.0.0/16" } } }
或
GET my-index-000001/_search { "query": { "term": { "ip_addr": "2001:db8::/48" } } }
还要注意,冒号是query_string
查询中的特殊字符,因此ipv6地址将需要进行转义。最简单的方法是在搜索值周围加上引号:
GET my-index-000001/_search { "query": { "query_string" : { "query": "ip_addr:\"2001:db8::/48\"" } } }
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
合成源可能会对 ip
字段值进行排序并删除重复项。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "ip": { "type": "ip" } } } } PUT idx/_doc/1 { "ip": ["192.168.0.1", "192.168.0.1", "10.10.12.123", "2001:db8::1:0:0:1", "::afff:4567:890a"] }
将变为:
{ "ip": ["::afff:4567:890a", "10.10.12.123", "192.168.0.1", "2001:db8::1:0:0:1"] }
IPv4 地址按照它们被视为以 ::ffff:0:0:0/96
为前缀的 IPv6 地址进行排序,如 rfc6144 所指定。
连接字段类型
editThe join
数据类型是一种特殊字段,用于在同一索引的文档中创建父子关系。
The relations
部分定义了文档中可能存在的一组关系,
每个关系由一个父名称和一个子名称组成。
我们不建议使用多级关系来复制关系模型。每一级关系在查询时都会增加内存和计算的开销。为了获得更好的搜索性能,请对数据进行反规范化处理。
父子关系可以定义如下:
PUT my-index-000001 { "mappings": { "properties": { "my_id": { "type": "keyword" }, "my_join_field": { "type": "join", "relations": { "question": "answer" } } } } }
要使用连接索引文档,必须在source
中提供关系名称和可选的文档父级。例如,以下示例在question
上下文中创建两个parent
文档:
PUT my-index-000001/_doc/1?refresh { "my_id": "1", "text": "This is a question", "my_join_field": { "name": "question" } } PUT my-index-000001/_doc/2?refresh { "my_id": "2", "text": "This is another question", "my_join_field": { "name": "question" } }
在索引父文档时,您可以选择仅指定关系的名称作为快捷方式,而不是将其封装在正常的对象表示法中:
PUT my-index-000001/_doc/1?refresh { "my_id": "1", "text": "This is a question", "my_join_field": "question" } PUT my-index-000001/_doc/2?refresh { "my_id": "2", "text": "This is another question", "my_join_field": "question" }
在索引子文档时,关系的名称以及文档的父ID必须添加到_source
中。
需要在同一个分片中索引父文档的血统,因此必须始终使用其更大的父ID来路由子文档。
例如,以下示例展示了如何索引两个子
文档:
PUT my-index-000001/_doc/3?routing=1&refresh { "my_id": "3", "text": "This is an answer", "my_join_field": { "name": "answer", "parent": "1" } } PUT my-index-000001/_doc/4?routing=1&refresh { "my_id": "4", "text": "This is another answer", "my_join_field": { "name": "answer", "parent": "1" } }
父连接与性能
editjoin 字段不应该像关系数据库中的连接那样使用。在 Elasticsearch 中,良好性能的关键是将数据反规范化到文档中。每个 join 字段,has_child
或 has_parent
查询都会对查询性能增加显著的开销。它还可能触发 全局序数 的构建。
唯一一个连接字段有意义的情况是,如果你的数据包含一对多的关系,其中一个实体的数量远远超过另一个实体。这种情况的一个例子是产品及其报价的使用场景。如果报价的数量远远超过产品的数量,那么将产品建模为父文档,将报价建模为子文档是有意义的。
父连接限制
edit使用父连接进行搜索
edit父连接创建一个字段来索引文档中关系的名称(my_parent
、my_child
,…)。
它还为每个父子关系创建一个字段。
这个字段的名字是join
字段的名字,后面跟着#
和关系中父节点的名字。
因此,例如对于my_parent
→ [my_child
, another_child
]关系,
join
字段会创建一个名为my_join_field#my_parent
的附加字段。
此字段包含文档链接到的父级 _id
,如果文档是子文档(my_child
或 another_child
),以及文档的 _id
,如果它是父文档(my_parent
)。
当搜索包含 join
字段的索引时,这两个字段总是会在搜索响应中返回:
GET my-index-000001/_search { "query": { "match_all": {} }, "sort": ["my_id"] }
将返回:
{ ..., "hits": { "total": { "value": 4, "relation": "eq" }, "max_score": null, "hits": [ { "_index": "my-index-000001", "_id": "1", "_score": null, "_source": { "my_id": "1", "text": "This is a question", "my_join_field": "question" }, "sort": [ "1" ] }, { "_index": "my-index-000001", "_id": "2", "_score": null, "_source": { "my_id": "2", "text": "This is another question", "my_join_field": "question" }, "sort": [ "2" ] }, { "_index": "my-index-000001", "_id": "3", "_score": null, "_routing": "1", "_source": { "my_id": "3", "text": "This is an answer", "my_join_field": { "name": "answer", "parent": "1" } }, "sort": [ "3" ] }, { "_index": "my-index-000001", "_id": "4", "_score": null, "_routing": "1", "_source": { "my_id": "4", "text": "This is another answer", "my_join_field": { "name": "answer", "parent": "1" } }, "sort": [ "4" ] } ] } }
父子连接查询和聚合
edit参见 has_child
和
has_parent
查询,
children
聚合,
以及 inner hits 了解更多信息。
在聚合和脚本中可以访问join
字段的值,并且可以使用parent_id
查询进行查询:
GET my-index-000001/_search { "query": { "parent_id": { "type": "answer", "id": "1" } }, "aggs": { "parents": { "terms": { "field": "my_join_field#question", "size": 10 } } }, "runtime_mappings": { "parent": { "type": "long", "script": """ emit(Integer.parseInt(doc['my_join_field#question'].value)) """ } }, "fields": [ { "field": "parent" } ] }
查询 |
|
在 |
|
在脚本中访问 |
全局序数
editThe join
field uses 全局序数 to speed up joins.
全局序数需要在分片发生任何更改后重建。存储在分片中的父ID值越多,重建join
字段的全局序数所需的时间就越长。
全局序号默认情况下是即时构建的:如果索引发生了变化,
join
字段的全局序号将在刷新过程中重建。
这可能会显著增加刷新的时间。然而,大多数情况下这是正确的权衡,否则全局序号将在第一次使用父-子查询或聚合时重建。
这可能会为您的用户引入显著的延迟峰值,通常情况下这会更糟糕,因为当发生大量写入时,可能会在单个刷新间隔内尝试重建多个 join
字段的全局序号。
当 join
字段不常使用而写操作频繁时,禁用预加载可能是有意义的:
PUT my-index-000001 { "mappings": { "properties": { "my_join_field": { "type": "join", "relations": { "question": "answer" }, "eager_global_ordinals": false } } } }
全局序数使用的堆内存量可以按父关系如下检查:
# Per-index GET _stats/fielddata?human&fields=my_join_field#question # Per-node per-index GET _nodes/stats/indices/fielddata?human&fields=my_join_field#question
每个父项的多个子项
edit也可以为单个父节点定义多个子节点:
多级父连接
edit我们不建议使用多级关系来复制关系模型。每一级关系在查询时都会增加内存和计算的开销。为了获得更好的搜索性能,请对数据进行反规范化处理。
多级父子关系:
PUT my-index-000001 { "mappings": { "properties": { "my_join_field": { "type": "join", "relations": { "question": ["answer", "comment"], "answer": "vote" } } } } }
上面的映射表示以下树:
question / \ / \ comment answer | | vote
索引一个孙文档需要一个路由
值等于祖父(血统中的更大父级):
关键词类型家族
edit关键词系列包括以下字段类型:
-
keyword
,用于结构化内容,如ID、电子邮件地址、主机名、状态代码、邮政编码或标签。 -
constant_keyword
用于始终包含相同值的关键字字段。 -
wildcard
用于非结构化的机器生成内容。wildcard
类型针对具有大值或高基数的字段进行了优化。
关键字字段通常用于排序、
聚合和词项级别查询,例如term
。
避免使用关键词字段进行全文搜索。请改用text
字段类型。
关键词字段类型
edit下面是一个基本keyword
字段映射的示例:
PUT my-index-000001 { "mappings": { "properties": { "tags": { "type": "keyword" } } } }
映射数字标识符
并非所有数值数据都应映射为数值字段数据类型。
Elasticsearch 优化了数值字段,例如 integer
或 long
,用于
range
查询。然而,keyword
字段
更适合 term
和其他
词项级别查询。
标识符,如ISBN或产品ID,很少用于范围
查询。然而,它们通常使用术语级查询来检索。
如果满足以下条件,请考虑将数值标识符映射为keyword
:
-
您不打算使用
range
查询来搜索标识符数据。 -
快速检索很重要。
term
查询在keyword
字段上的搜索通常比在数值字段上的term
搜索更快。
如果你不确定使用哪一个,你可以使用一个多字段来将数据映射为keyword
和数字数据类型。
基本关键词字段的参数
edit以下参数由 keyword
字段接受:
-
doc_values
-
字段是否应以列步长方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受
true
(默认)或false
。 -
eager_global_ordinals
-
全局序数是否应在刷新时立即加载?接受
true
或false
(默认)。在经常用于词条聚合的字段上启用此功能是一个好主意。 -
fields
- 多字段允许将相同的字符串值以多种方式进行索引,以满足不同的目的,例如一个字段用于搜索,而另一个多字段用于排序和聚合。
-
ignore_above
-
不要索引任何长度超过此值的字符串。默认值为
2147483647
,以便接受所有值。但请注意,默认的动态映射规则会创建一个子keyword
字段,该字段通过设置ignore_above: 256
来覆盖此默认值。 -
index
-
字段是否应快速可搜索?接受
true
(默认)和false
。仅启用了doc_values
的keyword
字段仍然可以查询,尽管速度较慢。 -
index_options
-
用于评分目的,索引中应存储哪些信息。
默认为
docs
,但也可以设置为freqs
,以在计算分数时考虑词频。 -
meta
- 字段的相关元数据。
-
norms
-
是否在评分查询时考虑字段长度。
接受
true
或false
(默认)。 -
null_value
-
接受一个字符串值,该值将替换任何显式的
null
值。默认为null
,这意味着该字段被视为缺失。请注意,如果使用了script
值,则不能设置此项。 -
on_script_error
-
定义如果在索引时由
script
参数定义的脚本抛出错误时应执行的操作。接受fail
(默认),这将导致整个文档被拒绝,以及continue
,这将把字段注册在文档的_ignored
元数据字段中并继续索引。此参数只能在设置了script
字段时设置。 -
script
-
如果设置此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档中为此字段设置了值,则文档将被拒绝并返回错误。
脚本格式与其运行时等效项相同。脚本发出的值将像往常一样进行规范化,如果它们的长度超过在
ignore_above
上设置的值,则将被忽略。 -
store
-
字段值是否应与
_source
字段分开存储和检索。接受true
或false
(默认)。 -
similarity
-
使用哪种评分算法或相似度。默认为
BM25
。 -
normalizer
-
如何在对关键词进行索引之前进行预处理。默认为
null
, 表示关键词保持原样。 -
split_queries_on_whitespace
-
是否应在为此字段构建查询时,将全文查询的输入按空格分割。
接受
true
或false
(默认)。 -
time_series_dimension
-
(可选,布尔值)
将字段标记为时间序列维度。默认为
false
。索引设置
index.mapping.dimension_fields.limit
限制了索引中的维度数量。维度字段具有以下约束:
-
The
doc_values
andindex
mapping parameters must betrue
. -
维度值用于标识文档的时间序列。如果在索引期间以任何方式更改维度值,文档将被存储为属于与预期不同的时间序列。因此,存在额外的约束:
-
The field cannot use a
normalizer
.
-
The field cannot use a
-
The
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
合成源可能会对keyword
字段进行排序并删除重复项。
例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "kwd": { "type": "keyword" } } } } PUT idx/_doc/1 { "kwd": ["foo", "foo", "bar", "baz"] }
将变为:
{ "kwd": ["bar", "baz", "foo"] }
如果一个keyword
字段将store
设置为true
,那么顺序和重复项将被保留。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "kwd": { "type": "keyword", "store": true } } } } PUT idx/_doc/1 { "kwd": ["foo", "foo", "bar", "baz"] }
将变为:
{ "kwd": ["foo", "foo", "bar", "baz"] }
长度超过 ignore_above
的值会被保留,但会被排序到末尾。
例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "kwd": { "type": "keyword", "ignore_above": 3 } } } } PUT idx/_doc/1 { "kwd": ["foo", "foo", "bang", "bar", "baz"] }
将变为:
{ "kwd": ["bar", "baz", "foo", "bang"] }
常量关键词字段类型
editConstant keyword 是 keyword
字段的一个特化,适用于索引中所有文档具有相同值的情况。
PUT logs-debug { "mappings": { "properties": { "@timestamp": { "type": "date" }, "message": { "type": "text" }, "level": { "type": "constant_keyword", "value": "debug" } } } }
constant_keyword
支持与 keyword
字段相同的查询和聚合,但利用了所有文档在每个索引中具有相同值的事实,以更高效地执行查询。
提交没有字段值的文档或字段值等于映射中配置的值的文档都是允许的。以下两个索引请求是等效的:
POST logs-debug/_doc { "date": "2019-12-12", "message": "Starting up Elasticsearch", "level": "debug" } POST logs-debug/_doc { "date": "2019-12-12", "message": "Starting up Elasticsearch" }
然而,提供一个与映射中配置的值不同的值是不允许的。
如果在映射中没有提供value
,字段将根据第一个索引文档中包含的值自动配置自身。
虽然这种行为可能很方便,但请注意,这意味着如果一个有毒的文档具有错误的值,它可能会导致所有其他文档被拒绝。
在未提供值之前(无论是通过映射还是来自文档),对该字段的查询将不会匹配任何文档。这包括 exists
查询。
字段的值
在设置后不能更改。
常量关键词字段的参数
edit接受的映射参数如下:
字段的元数据。 |
|
|
与索引中所有文档关联的值。如果未提供此参数,则根据第一个被索引的文档设置。 |
通配符字段类型
editThe wildcard
字段类型是一种专门的关键字字段,用于非结构化的机器生成内容,您计划使用类似 grep 的
wildcard
和 regexp
查询进行搜索。wildcard
类型针对具有大值或高基数的字段进行了优化。
在内部,wildcard
字段使用 ngrams 对整个字段值进行索引并存储完整字符串。
索引用作粗略过滤器,以减少通过检索和检查完整值来检查的值的数量。
此字段特别适合在日志行上运行类似 grep 的查询。存储成本通常低于 keyword
字段,但对于完整术语的精确匹配搜索速度较慢。如果字段值共享许多前缀,例如同一网站的 URL,则 wildcard
字段的存储成本可能高于等效的 keyword
字段。
您可以按如下方式索引和搜索通配符字段
PUT my-index-000001 { "mappings": { "properties": { "my_wildcard": { "type": "wildcard" } } } } PUT my-index-000001/_doc/1 { "my_wildcard" : "This string can be quite lengthy" } GET my-index-000001/_search { "query": { "wildcard": { "my_wildcard": { "value": "*quite*lengthy" } } } }
通配符字段的参数
edit以下参数被wildcard
字段接受:
接受一个字符串值,该值将替换任何显式的 |
|
不要索引任何长度超过此值的字符串。默认值为 |
限制
edit-
wildcard
字段像关键字字段一样未被分词,因此不支持依赖词位置的查询,如短语查询。 -
当运行
wildcard
查询时,任何rewrite
参数都会被忽略。评分始终是一个常数分数。
合成 _source
edit合成源可能会对通配符
字段值进行排序。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "card": { "type": "wildcard" } } } } PUT idx/_doc/1 { "card": ["king", "ace", "ace", "jack"] }
将变为:
{ "card": ["ace", "jack", "king"] }
嵌套字段类型
editThe nested
type 是 object
数据类型的特殊版本,
它允许对象数组以一种可以彼此独立查询的方式进行索引。
当摄取具有大量任意键值对时,您可以考虑将每个键值对建模为其自己的嵌套文档,其中包含key
和value
字段。相反,考虑使用flattened数据类型,它将整个对象映射为单个字段,并允许对其内容进行简单搜索。嵌套文档和查询通常是昂贵的,因此在此用例中使用flattened
数据类型是一个更好的选择。
嵌套字段在 Kibana 中的支持不完整。尽管它们在 Discover 中可见且可搜索,但无法在 Lens 中用于构建可视化。
对象数组如何被展平
editElasticsearch 没有内部对象的概念。因此,它将对象层次结构扁平化为一个简单的字段名称和值的列表。例如,考虑以下文档:
PUT my-index-000001/_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 AND smith
:
GET my-index-000001/_search { "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "Smith" }} ] } } }
使用 nested
字段处理对象数组
edit如果你需要索引对象数组并保持数组中每个对象的独立性,请使用 nested
数据类型,而不是 object
数据类型。
在内部,嵌套对象将数组中的每个对象索引为单独的隐藏文档,这意味着可以使用nested
查询独立查询每个嵌套对象:
PUT my-index-000001 { "mappings": { "properties": { "user": { "type": "nested" } } } } PUT my-index-000001/_doc/1 { "group" : "fans", "user" : [ { "first" : "John", "last" : "Smith" }, { "first" : "Alice", "last" : "White" } ] } GET my-index-000001/_search { "query": { "nested": { "path": "user", "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "Smith" }} ] } } } } } GET my-index-000001/_search { "query": { "nested": { "path": "user", "query": { "bool": { "must": [ { "match": { "user.first": "Alice" }}, { "match": { "user.last": "White" }} ] } }, "inner_hits": { "highlight": { "fields": { "user.first": {} } } } } } }
与嵌套
文档交互
edit嵌套文档可以是:
-
使用
nested
查询进行查询。 -
使用
nested
和reverse_nested
聚合进行分析。 - 使用嵌套排序进行排序。
- 使用嵌套内部命中进行检索和突出显示。
因为嵌套文档是作为单独的文档进行索引的,它们只能在 nested
查询、nested
/reverse_nested
聚合或 嵌套内部命中 的范围内访问。
例如,如果嵌套文档中的字符串字段设置了
index_options
为 offsets
,以允许在突出显示期间使用词频信息,这些偏移量在主突出显示阶段将不可用。相反,需要通过
嵌套内部命中 来执行突出显示。当通过 docvalue_fields
或 stored_fields
在搜索期间加载字段时,同样需要考虑这一点。
嵌套字段的参数
edit以下参数由 nested
字段接受:
-
dynamic
-
(可选,字符串)
是否应将新
属性
动态添加到现有嵌套对象中。接受true
(默认)、false
和strict
。 -
properties
-
(可选, 对象)
嵌套对象中的字段, 可以是任何
数据类型, 包括
nested
。可以向现有嵌套对象添加新属性。 -
include_in_parent
-
(可选,布尔值)
如果为
true
,嵌套对象中的所有字段也会作为标准(扁平)字段添加到父文档中。默认为false
。 -
include_in_root
-
(可选,布尔值)
如果为
true
,嵌套对象中的所有字段也会作为标准(扁平)字段添加到根文档中。默认为false
。
关于嵌套
映射和对象的限制
edit如前所述,每个嵌套对象都被索引为一个单独的Lucene文档。
继续前面的例子,如果我们索引了一个包含100个user
对象的单个文档,
那么将创建101个Lucene文档:一个用于父文档,一个用于每个
嵌套对象。由于nested
映射相关的开销,Elasticsearch设置了
一些措施来防止性能问题:
-
index.mapping.nested_fields.limit
-
索引中不同
嵌套
映射的最大数量。嵌套
类型应仅在特殊情况下使用,当需要独立查询对象数组时。为了防止设计不良的映射,此设置限制了每个索引的唯一嵌套
类型的数量。默认值为50
。
在前面的示例中,user
映射将仅计为 1 个此限制。
-
index.mapping.nested_objects.limit
-
单个文档在所有
嵌套
类型中可以包含的最大嵌套JSON对象数量。此限制有助于防止当文档包含过多嵌套对象时出现内存不足错误。默认值为10000
。
为了说明此设置的工作原理,请考虑在前一个示例映射中添加另一个名为 comments
的 nested
类型。对于每个文档,它包含的 user
和 comment
对象的总数必须低于限制。
关于防止映射爆炸的附加设置,请参阅防止映射爆炸。
数值字段类型
edit支持以下数值类型:
|
一个有符号的64位整数,最小值为 |
|
一个有符号的32位整数,最小值为 |
|
一个有符号的16位整数,最小值为 |
|
一个有符号的8位整数,最小值为 |
|
一个双精度64位IEEE 754浮点数,限制为有限值。 |
|
一个单精度32位IEEE 754浮点数,限制为有限值。 |
|
一个半精度16位IEEE 754浮点数,限制为有限值。 |
|
一个由 |
|
一个无符号的64位整数,最小值为0,最大值为 |
下面是一个配置带有数值字段的映射的示例:
PUT my-index-000001 { "mappings": { "properties": { "number_of_bytes": { "type": "integer" }, "time_in_seconds": { "type": "float" }, "price": { "type": "scaled_float", "scaling_factor": 100 } } } }
The double
, float
and half_float
类型认为 -0.0
和
+0.0
是不同的值。因此,对 -0.0
进行 term
查询
将不会匹配 +0.0
,反之亦然。范围查询也是如此:
如果上界是 -0.0
,则 +0.0
不会匹配,如果下界是
+0.0
,则 -0.0
不会匹配。
我应该使用哪种类型?
edit就整数类型(byte
、short
、integer
和 long
)而言,
您应该选择足够满足您使用场景的最小类型。这将有助于索引和搜索更加高效。但请注意,存储是基于实际存储的值进行优化的,因此选择一种类型而不是另一种类型不会对存储需求产生影响。
对于浮点类型,通常更高效的做法是使用缩放因子将浮点数据存储为整数,这就是scaled_float
类型在底层所做的事情。例如,一个price
字段可以存储在一个scaled_float
中,缩放因子为100
。所有API的操作都像该字段存储为双精度数一样,但在底层,Elasticsearch会使用以分为单位的数值,即price*100
,这是一个整数。这主要是为了节省磁盘空间,因为整数比浮点数更容易压缩。scaled_float
也可以用于以精度换取磁盘空间。例如,假设你正在跟踪CPU利用率,其值在0
到1
之间。通常情况下,CPU利用率是12.7%
还是13%
并不重要,因此你可以使用缩放因子为100
的scaled_float
,以便将CPU利用率四舍五入到最近的百分比,从而节省空间。
如果 scaled_float
不适合,那么你应该选择浮点类型中最小的类型,以满足使用场景:double
、float
和 half_float
。以下是一个比较这些类型的表格,以帮助做出决策。
Type | Minimum value | Maximum value | Significant bits / digits |
Example precision loss |
---|---|---|---|---|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
映射数字标识符
并非所有数值数据都应映射为数值字段数据类型。
Elasticsearch 优化了数值字段,例如 integer
或 long
,用于
range
查询。然而,keyword
字段
更适合 term
和其他
词项级别查询。
标识符,如ISBN或产品ID,很少用于范围
查询。然而,它们通常使用术语级查询来检索。
如果满足以下条件,请考虑将数值标识符映射为keyword
:
-
您不打算使用
range
查询来搜索标识符数据。 -
快速检索很重要。
term
查询在keyword
字段上的搜索通常比在数值字段上的term
搜索更快。
如果你不确定使用哪一个,你可以使用一个多字段来将数据映射为keyword
和数字数据类型。
数值字段的参数
edit以下参数由数值类型接受:
-
coerce
-
尝试将字符串转换为数字并截断整数的分数部分。
接受
true
(默认)和false
。不适用于unsigned_long
。 请注意,如果使用了script
参数,则无法设置此项。 -
doc_values
-
字段是否应以列步长方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受
true
(默认)或false
。 -
ignore_malformed
-
如果
true
,格式错误的数字将被忽略。如果false
(默认),格式错误的数字将抛出异常并拒绝整个文档。请注意,如果使用了script
参数,则无法设置此选项。 -
index
-
该字段是否应快速可搜索?接受
true
(默认)和false
。仅启用了doc_values
的数值字段也可以查询,尽管速度较慢。 -
meta
- 字段的相关元数据。
-
null_value
-
接受与字段相同
类型
的数值,用于替换任何显式的null
值。默认为null
,这意味着该字段被视为缺失。请注意,如果使用了script
参数,则不能设置此项。 -
on_script_error
-
定义如果在索引时由
script
参数定义的脚本抛出错误时应执行的操作。接受fail
(默认),这将导致整个文档被拒绝,以及continue
,这将把字段注册在文档的_ignored
元数据字段中并继续索引。此参数只能在设置了script
字段时设置。 -
script
-
如果设置了此参数,则该字段将索引由此脚本生成的值,而不是直接从源中读取值。如果在输入文档中为此字段设置了值,则文档将被拒绝并返回错误。
脚本的格式与其运行时等效项相同。脚本只能配置在
long
和double
字段类型上。 -
store
-
字段值是否应与
_source
字段分开存储和检索。接受true
或false
(默认)。 -
time_series_dimension
-
(可选,布尔值)
将字段标记为时间序列维度。默认为
false
。索引设置
index.mapping.dimension_fields.limit
限制了索引中的维度数量。维度字段具有以下约束:
-
The
doc_values
andindex
mapping parameters must betrue
.
在数值字段类型中,只有
byte
、short
、integer
、long
和unsigned_long
字段支持此参数。数值字段不能同时是时间序列维度和时间序列指标。
-
The
-
time_series_metric
-
(可选,字符串) 将字段标记为时间序列指标。该值是指标类型。您不能更新现有字段的此参数。
数值型字段的有效
time_series_metric
值-
counter
-
一种累积指标,仅单调递增或重置为
0
(零)。例如,错误计数或已完成任务的计数。 -
gauge
- 表示可以任意增加或减少的单个数值的指标。例如,温度或可用磁盘空间。
-
null
(默认) - 不是时间序列指标。
对于数值型时间序列指标,
doc_values
参数必须为true
。一个数值字段不能同时是时间序列维度和时间序列指标。 -
参数为 scaled_float
editscaled_float
接受一个额外的参数:
|
在编码值时使用的缩放因子。值将在索引时乘以这个因子并四舍五入到最接近的长整型值。例如,一个 |
scaled_float
饱和度
editscaled_float
存储为一个 long
值,该值是原始值乘以缩放因子的乘积。如果乘法结果超出了 long
的范围,则该值会饱和到 long
的最小值或最大值。例如,如果缩放因子是 100
且值为 92233720368547758.08
,则预期值为 9223372036854775808
。然而,存储的值是 9223372036854775807
,即 long
的最大值。
这可能会导致在使用范围查询时出现意外结果,当缩放因子或提供的float
值特别大时。
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
所有数值字段在其默认配置中都支持合成
_source
。合成_source
不能与copy_to
一起使用,也不能与doc_values
禁用的情况一起使用。
合成源可能会对数值字段值进行排序。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "long": { "type": "long" } } } } PUT idx/_doc/1 { "long": [0, 0, -123466, 87612] }
将变为:
{ "long": [-123466, 0, 0, 87612] }
缩放的浮点数将始终应用它们的缩放因子,因此:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "f": { "type": "scaled_float", "scaling_factor": 0.01 } } } } PUT idx/_doc/1 { "f": 123 }
将变为:
{ "f": 100.0 }
对象字段类型
editJSON文档本质上是分层的:文档可能包含内部对象,而这些内部对象本身可能包含内部对象:
PUT my-index-000001/_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" }
上述文档的显式映射可能如下所示:
PUT my-index-000001 { "mappings": { "properties": { "region": { "type": "keyword" }, "manager": { "properties": { "age": { "type": "integer" }, "name": { "properties": { "first": { "type": "text" }, "last": { "type": "text" } } } } } } } }
您不需要将字段 type
显式设置为 object
,因为这是默认值。
透传对象字段类型
edit传递对象通过允许在不包含传递对象名称作为前缀的情况下访问其子字段,扩展了对象的功能。例如:
PUT my-index-000001 { "mappings": { "properties": { "attributes": { "type": "passthrough", "priority": 10, "properties": { "id": { "type": "keyword" } } } } } } PUT my-index-000001/_doc/1 { "attributes" : { "id": "foo", "zone": 10 } } GET my-index-000001/_search { "query": { "bool": { "must": [ { "match": { "id": "foo" }}, { "match": { "zone": 10 }} ] } } } GET my-index-000001/_search { "query": { "bool": { "must": [ { "match": { "attributes.id": "foo" }}, { "match": { "attributes.zone": 10 }} ] } } }
冲突解决
edit可能会出现名称冲突的情况,这些字段定义在不同的作用域内:
-
透传对象定义在与透传对象子字段相同名称的字段旁边,例如。
PUT my-index-000001/_doc/1 { "attributes" : { "id": "foo" }, "id": "bar" }
在这种情况下,对
id
的引用指向根级别的字段,而字段attributes.id
只能通过完整路径访问。 -
在同一个对象内定义了两个(或更多)透传对象,并且它们包含具有相同名称的字段,例如。
PUT my-index-000002 { "mappings": { "properties": { "attributes": { "type": "passthrough", "priority": 10, "properties": { "id": { "type": "keyword" } } }, "resource.attributes": { "type": "passthrough", "priority": 20, "properties": { "id": { "type": "keyword" } } } } } }
在这种情况下,参数
priority
用于冲突解决,值较高的优先级更高。在上面的示例中,resource.attributes
的优先级高于attributes
,因此对id
的引用指向resource.attributes
字段内的字段。attributes.id
仍然可以通过其完整路径访问。
将子字段定义为时间序列维度
edit可以将透传字段配置为 时间序列维度 的容器。 在这种情况下,所有子字段在幕后都会被标注为相同的参数,并且它们也会被包含在 基于维度的路由路径 和 tsid 计算中,从而简化了 TSDS 的设置:
PUT _index_template/my-metrics { "index_patterns": ["metrics-mymetrics-*"], "priority": 200, "data_stream": { }, "template": { "settings": { "index.mode": "time_series" }, "mappings": { "properties": { "attributes": { "type": "passthrough", "priority": 10, "time_series_dimension": true, "properties": { "host.name": { "type": "keyword" } } }, "cpu": { "type": "integer", "time_series_metric": "counter" } } } } } POST metrics-mymetrics-test/_doc { "@timestamp": "2020-01-01T00:00:00.000Z", "attributes" : { "host.name": "foo", "zone": "bar" }, "cpu": 10 }
在上面的示例中,attributes
被定义为一个维度容器。它的子字段 host.name
(静态)和 zone
(动态)被包含在路由路径和tsid中,并且可以在查询中引用,而无需使用 attributes.
前缀。
Percolator 字段类型
editThe percolator
字段类型将一个json结构解析为一个本地查询并存储该查询,以便percolate query可以使用它来匹配提供的文档。
任何包含json对象的字段都可以配置为percolator字段。percolator字段类型没有设置。只需配置percolator
字段类型就足以指示Elasticsearch将字段视为查询。
如果以下映射配置了query
字段的percolator
字段类型:
PUT my-index-000001 { "mappings": { "properties": { "query": { "type": "percolator" }, "field": { "type": "text" } } } }
然后你可以索引一个查询:
PUT my-index-000001/_doc/match_value { "query": { "match": { "field": "value" } } }
重新索引你的 percolator 查询
edit重新索引 percolator 查询有时是必要的,以利用新版本中对 percolator
字段类型所做的改进。
可以通过使用reindex api来重新索引percolator查询。 让我们来看一下以下具有percolator字段类型的索引:
PUT index { "mappings": { "properties": { "query" : { "type" : "percolator" }, "body" : { "type": "text" } } } } POST _aliases { "actions": [ { "add": { "index": "index", "alias": "queries" } } ] } PUT queries/_doc/1?refresh { "query" : { "match" : { "body" : "quick brown fox" } } }
假设你要升级到一个新的主要版本,为了让新的 Elasticsearch 版本仍然能够读取你的查询,你需要在当前的 Elasticsearch 版本上将查询重新索引到一个新的索引中:
PUT new_index { "mappings": { "properties": { "query" : { "type" : "percolator" }, "body" : { "type": "text" } } } } POST /_reindex?refresh { "source": { "index": "index" }, "dest": { "index": "new_index" } } POST _aliases { "actions": [ { "remove": { "index" : "index", "alias": "queries" } }, { "add": { "index": "new_index", "alias": "queries" } } ] }
通过 queries
别名执行 percolate
查询:
GET /queries/_search { "query": { "percolate" : { "field" : "query", "document" : { "body" : "fox jumps over the lazy dog" } } } }
现在返回来自新索引的匹配项:
{ "took": 3, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped" : 0, "failed": 0 }, "hits": { "total" : { "value": 1, "relation": "eq" }, "max_score": 0.13076457, "hits": [ { "_index": "new_index", "_id": "1", "_score": 0.13076457, "_source": { "query": { "match": { "body": "quick brown fox" } } }, "fields" : { "_percolator_document_slot" : [0] } } ] } }
优化查询时间文本分析
edit当 percolator 验证一个 percolator 候选匹配时,它将解析、执行查询时文本分析,并在被 percolated 的文档上实际运行 percolator 查询。这是为每个候选匹配完成的,并且每次执行 percolate
查询时都会进行。如果你的查询时文本分析是查询解析中相对昂贵的部分,那么文本分析可能会成为 percolating 时花费时间的主要因素。当 percolator 最终验证许多候选 percolator 查询匹配时,这种查询解析开销可能会变得明显。
为了避免在渗透时间进行文本分析中最昂贵的部分。可以选择在索引渗透器查询时进行文本分析的昂贵部分。这需要使用两种不同的分析器。第一个分析器实际上执行需要执行的文本分析(昂贵部分)。第二个分析器(通常是空格)只是分割第一个分析器生成的标记。然后,在索引渗透器查询之前,应使用分析API以更昂贵的分析器分析查询文本。分析API的结果,即标记,应用于替换渗透器查询中的原始查询文本。重要的是,查询现在应配置为覆盖映射中的分析器,并仅使用第二个分析器。大多数基于文本的查询支持一个analyzer
选项(match
, query_string
, simple_query_string
)。使用这种方法,昂贵的文本分析只需执行一次,而不是多次。
让我们通过一个简化的例子来演示这个工作流程。
假设我们要索引以下 percolator 查询:
{ "query" : { "match" : { "body" : { "query" : "missing bicycles" } } } }
使用这些设置和映射:
PUT /test_index { "settings": { "analysis": { "analyzer": { "my_analyzer" : { "tokenizer": "standard", "filter" : ["lowercase", "porter_stem"] } } } }, "mappings": { "properties": { "query" : { "type": "percolator" }, "body" : { "type": "text", "analyzer": "my_analyzer" } } } }
首先,我们需要使用分析 API 在索引之前执行文本分析:
POST /test_index/_analyze { "analyzer" : "my_analyzer", "text" : "missing bicycles" }
这将产生以下响应:
{ "tokens": [ { "token": "miss", "start_offset": 0, "end_offset": 7, "type": "<ALPHANUM>", "position": 0 }, { "token": "bicycl", "start_offset": 8, "end_offset": 16, "type": "<ALPHANUM>", "position": 1 } ] }
返回的订单中的所有令牌都需要替换渗透器查询中的查询文本:
PUT /test_index/_doc/1?refresh { "query" : { "match" : { "body" : { "query" : "miss bicycl", "analyzer" : "whitespace" } } } }
在这里选择一个空白分析器是很重要的,否则将使用映射中定义的分析器,这将违背使用此工作流程的目的。请注意, |
在索引 percolator 流程之前,应该对每个 percolator 查询进行分析 API 处理。
在渗透时间没有任何变化,percolate
查询可以正常定义:
GET /test_index/_search { "query": { "percolate" : { "field" : "query", "document" : { "body" : "Bycicles are missing" } } } }
这将产生如下响应:
{ "took": 6, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped" : 0, "failed": 0 }, "hits": { "total" : { "value": 1, "relation": "eq" }, "max_score": 0.13076457, "hits": [ { "_index": "test_index", "_id": "1", "_score": 0.13076457, "_source": { "query": { "match": { "body": { "query": "miss bicycl", "analyzer": "whitespace" } } } }, "fields" : { "_percolator_document_slot" : [0] } } ] } }
优化通配符查询。
edit通配符查询对于 percolator 来说比其他查询更耗费资源,特别是当通配符表达式很大时。
在带有前缀通配符表达式的通配符
查询或仅前缀
查询的情况下,可以使用edge_ngram
分词过滤器将这些查询替换为在配置了edge_ngram
分词过滤器的字段上的常规term
查询。
创建带有自定义分析设置的索引:
PUT my_queries1 { "settings": { "analysis": { "analyzer": { "wildcard_prefix": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "wildcard_edge_ngram" ] } }, "filter": { "wildcard_edge_ngram": { "type": "edge_ngram", "min_gram": 1, "max_gram": 32 } } } }, "mappings": { "properties": { "query": { "type": "percolator" }, "my_field": { "type": "text", "fields": { "prefix": { "type": "text", "analyzer": "wildcard_prefix", "search_analyzer": "standard" } } } } } }
仅在索引时生成前缀标记的分析器。 |
|
根据您的前缀搜索需求,增加 |
|
此多字段应用于使用 |
然后,不索引以下查询:
{ "query": { "wildcard": { "my_field": "abc*" } } }
下面的查询应该被索引:
PUT /my_queries1/_doc/1?refresh { "query": { "term": { "my_field.prefix": "abc" } } }
这种方式可以比第一个查询更高效地处理第二个查询。
以下搜索请求将与之前索引的 percolator 查询匹配:
GET /my_queries1/_search { "query": { "percolate": { "field": "query", "document": { "my_field": "abcd" } } } }
{ "took": 6, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total" : { "value": 1, "relation": "eq" }, "max_score": 0.18864399, "hits": [ { "_index": "my_queries1", "_id": "1", "_score": 0.18864399, "_source": { "query": { "term": { "my_field.prefix": "abc" } } }, "fields": { "_percolator_document_slot": [ 0 ] } } ] } }
同样的技术也可以用于加速后缀通配符搜索。通过在使用 edge_ngram
分词器之前使用 reverse
分词器。
PUT my_queries2 { "settings": { "analysis": { "analyzer": { "wildcard_suffix": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "reverse", "wildcard_edge_ngram" ] }, "wildcard_suffix_search_time": { "type": "custom", "tokenizer": "standard", "filter": [ "lowercase", "reverse" ] } }, "filter": { "wildcard_edge_ngram": { "type": "edge_ngram", "min_gram": 1, "max_gram": 32 } } } }, "mappings": { "properties": { "query": { "type": "percolator" }, "my_field": { "type": "text", "fields": { "suffix": { "type": "text", "analyzer": "wildcard_suffix", "search_analyzer": "wildcard_suffix_search_time" } } } } } }
然后,不索引以下查询:
{ "query": { "wildcard": { "my_field": "*xyz" } } }
以下查询应被索引:
以下搜索请求将与之前索引的 percolator 查询匹配:
GET /my_queries2/_search { "query": { "percolate": { "field": "query", "document": { "my_field": "wxyz" } } } }
专用渗透器索引
editPercolate 查询可以添加到任何索引中。与将 percolate 查询添加到数据所在的索引不同,这些查询也可以添加到一个专用的索引中。这样做的好处是,这个专用的 percolator 索引可以有自己的索引设置(例如主分片和副本分片的数量)。如果你选择使用专用的 percolate 索引,你需要确保普通索引的映射也在 percolate 索引中可用。否则,percolate 查询可能会被错误解析。
强制未映射字段作为字符串处理
edit在某些情况下,无法确定会注册哪种类型的 percolator 查询,如果 percolator 查询引用的字段没有字段映射,则添加 percolator 查询会失败。这意味着需要更新映射以包含具有适当设置的字段,然后才能添加 percolator 查询。但有时,如果所有未映射的字段都被视为默认文本字段,就足够了。在这种情况下,可以将 index.percolator.map_unmapped_fields_as_text
设置为 true
(默认为 false
),然后如果 percolator 查询中引用的字段不存在,它将被视为默认文本字段,从而添加 percolator 查询不会失败。
限制
edit父/子
edit因为percolate
查询是逐个处理文档的,所以它不支持针对子文档运行的查询和过滤器,例如has_child
和has_parent
。
获取查询
edit在查询解析期间,有许多查询通过get调用来获取数据。例如,使用terms lookup时的terms
查询,使用索引脚本时的template
查询,以及使用预索引形状时的geo_shape
查询。当这些查询被percolator
字段类型索引时,get调用只执行一次。因此,每次percolator
查询评估这些查询时,都会使用索引时获取的术语、形状等。需要注意的是,这些查询每次在主分片和副本分片上索引percolator查询时,都会进行术语的获取,因此实际索引的术语在分片副本之间可能会有所不同,如果在索引期间源索引发生了变化。
脚本查询
edit在 script
查询中的脚本只能访问 doc values 字段。percolate
查询将提供的文档索引到内存中的索引中。这个内存中的索引不支持存储字段,因此 _source
字段和其他存储字段不会被存储。这就是为什么在 script
查询中 _source
和其他存储字段不可用的原因。
字段别名
edit包含字段别名的Percolator查询可能不会总是按预期行为执行。特别是,如果注册了一个包含字段别名的Percolator查询,然后在该映射中更新该别名以引用不同的字段,存储的查询仍将引用原始目标字段。要获取字段别名的更改,必须显式地重新索引Percolator查询。
点字段类型
editThe point
数据类型有助于索引和搜索
任意 x, y
对,这些对位于二维平面坐标系中。
您可以使用形状查询来查询此类文档。
与geo_shape和geo_point一样,point
可以在GeoJSON
和Well-Known Text格式中指定。
然而,出于便利和历史原因,还支持许多其他格式。
总共有五种方式可以指定一个笛卡尔点,如下所示:
PUT my-index-000001 { "mappings": { "properties": { "location": { "type": "point" } } } } PUT my-index-000001/_doc/1 { "text": "Point as an object using GeoJSON format", "location": { "type": "Point", "coordinates": [-71.34, 41.12] } } PUT my-index-000001/_doc/2 { "text": "Point as a WKT POINT primitive", "location" : "POINT (-71.34 41.12)" } PUT my-index-000001/_doc/3 { "text": "Point as an object with 'x' and 'y' keys", "location": { "x": -71.34, "y": 41.12 } } PUT my-index-000001/_doc/4 { "text": "Point as an array", "location": [ -71.34, 41.12 ] } PUT my-index-000001/_doc/5 { "text": "Point as a string", "location": "-71.34,41.12" }
点表示为一个对象,采用GeoJSON格式,包含 |
|
点表示为Well-Known Text
格式为: |
|
点表示为一个对象,包含 |
|
点表示为数组,格式为:[ |
|
点表示为字符串,格式为: |
与geo-point字段类型的情况不同,
坐标x
和y
的顺序在上述所有格式中都是相同的。
提供给索引器的坐标是单精度浮点值,因此该字段保证了与Java虚拟机提供的相同的精度(通常为1E-38
)。
point
字段的参数
edit以下参数由 point
字段接受:
如果 |
|
|
如果为 |
接受一个点值,该值将替换任何显式的 |
排序和检索点
edit目前无法直接对点进行排序或检索它们的字段。point
值只能通过 _source
字段检索。
范围字段类型
edit范围字段类型表示一个在上下限之间的连续值范围。例如,一个范围可以表示十月的任何日期或0到9之间的任何整数。它们使用操作符gt
或gte
来定义下限,以及lt
或lte
来定义上限。它们可以用于查询,并且对聚合的支持有限。唯一支持的聚合是直方图和基数。
支持以下范围类型:
|
一系列带符号的32位整数,最小值为 |
|
一系列单精度32位IEEE 754浮点值。 |
|
一系列带符号的64位整数,最小值为 |
|
一系列双精度64位IEEE 754浮点值。 |
|
一系列的 |
|
下面是一个配置包含各种范围字段的映射的示例,随后是一个索引多个范围类型的示例。
PUT range_index { "settings": { "number_of_shards": 2 }, "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, "lt" : 20 }, "time_frame" : { "gte" : "2015-10-31 12:00:00", "lte" : "2015-11-01" } }
|
|
示例:对一场有10到20名与会者的会议进行索引,不包括20。 |
|
使用日期时间戳的示例日期范围。 |
以下是在名为“expected_attendees”的integer_range
字段上进行的术语查询示例。
12 是范围内的一个值,因此它将匹配。
GET range_index/_search { "query" : { "term" : { "expected_attendees" : { "value": 12 } } } }
上述查询产生的结果。
{ "took": 13, "timed_out": false, "_shards" : { "total": 2, "successful": 2, "skipped" : 0, "failed": 0 }, "hits" : { "total" : { "value": 1, "relation": "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "range_index", "_id" : "1", "_score" : 1.0, "_source" : { "expected_attendees" : { "gte" : 10, "lt" : 20 }, "time_frame" : { "gte" : "2015-10-31 12:00:00", "lte" : "2015-11-01" } } } ] } }
以下是一个在名为“time_frame”的date_range
字段上进行date_range
查询的示例。
GET range_index/_search { "query" : { "range" : { "time_frame" : { "gte" : "2015-10-31", "lte" : "2015-11-01", "relation" : "within" } } } }
此查询产生类似的结果:
{ "took": 13, "timed_out": false, "_shards" : { "total": 2, "successful": 2, "skipped" : 0, "failed": 0 }, "hits" : { "total" : { "value": 1, "relation": "eq" }, "max_score" : 1.0, "hits" : [ { "_index" : "range_index", "_id" : "1", "_score" : 1.0, "_source" : { "expected_attendees" : { "gte" : 10, "lt" : 20 }, "time_frame" : { "gte" : "2015-10-31 12:00:00", "lte" : "2015-11-01" } } } ] } }
IP 范围
edit除了上述的范围格式外,IP范围还可以使用CIDR表示法提供:
PUT range_index/_mapping { "properties": { "ip_allowlist": { "type": "ip_range" } } } PUT range_index/_doc/2 { "ip_allowlist" : "192.168.0.0/16" }
范围字段的参数
edit以下参数由范围类型接受:
尝试将字符串转换为数字并截断整数的分数部分。
接受 |
|
字段是否应以列步长的方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受 |
|
字段是否应可搜索?接受 |
|
字段值是否应与 |
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
range
字段在其默认配置中支持 synthetic _source
。
合成源可能会对range
字段值进行排序并删除所有range
字段(除了ip_range
)的重复项。范围按其下限排序,然后按上限排序。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "long_range" } } } } PUT idx/_doc/1 { "my_range": [ { "gte": 200, "lte": 300 }, { "gte": 1, "lte": 100 }, { "gte": 200, "lte": 300 }, { "gte": 200, "lte": 500 } ] }
将变为:
{ "my_range": [ { "gte": 1, "lte": 100 }, { "gte": 200, "lte": 300 }, { "gte": 200, "lte": 500 } ] }
字段 ip_range
的值未排序,但原始顺序未保留。重复的范围被删除。如果 ip_range
字段的值以 CIDR 形式提供,它将在合成源中表示为一系列 IP 地址。
例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "ip_range" } } } } PUT idx/_doc/1 { "my_range": [ "10.0.0.0/24", { "gte": "10.0.0.0", "lte": "10.0.0.255" } ] }
将变为:
{ "my_range": { "gte": "10.0.0.0", "lte": "10.0.0.255" } }
范围字段值始终表示为两侧都包含,并相应地调整边界。范围边界的默认值表示为null
。即使范围边界是显式提供的,这也是正确的。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "long_range" } } } } PUT idx/_doc/1 { "my_range": { "gt": 200, "lt": 300 } }
将变为:
{ "my_range": { "gte": 201, "lte": 299 } }
范围边界的默认值在合成源中表示为null
。即使范围边界明确提供了默认值,这也是成立的。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "integer_range" } } } } PUT idx/_doc/1 { "my_range": { "lte": 2147483647 } }
将变为:
{ "my_range": { "gte": null, "lte": null } }
date
范围使用提供的 format
格式化,或者默认使用 yyyy-MM-dd'T'HH:mm:ss.SSSZ
格式。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "my_range": { "type": "date_range" } } } } PUT idx/_doc/1 { "my_range": [ { "gte": 1504224000000, "lte": 1504569600000 }, { "gte": "2017-09-01", "lte": "2017-09-10" } ] }
将变为:
{ "my_range": [ { "gte": "2017-09-01T00:00:00.000Z", "lte": "2017-09-05T00:00:00.000Z" }, { "gte": "2017-09-01T00:00:00.000Z", "lte": "2017-09-10T23:59:59.999Z" } ] }
排名特征字段类型
edit一个 rank_feature
字段可以索引数字,以便它们可以在查询中用于提升文档,使用 rank_feature
查询。
PUT my-index-000001 { "mappings": { "properties": { "pagerank": { "type": "rank_feature" }, "url_length": { "type": "rank_feature", "positive_score_impact": false } } } } PUT my-index-000001/_doc/1 { "pagerank": 8, "url_length": 22 } GET my-index-000001/_search { "query": { "rank_feature": { "field": "pagerank" } } }
rank_feature
字段仅支持单值字段和严格正值。多值字段和负值将被拒绝。
rank_feature
字段不支持查询、排序或聚合。它们只能在 rank_feature
查询中使用。
rank_feature
字段仅保留9个有效位用于精度,这相当于大约0.4%的相对误差。
与得分负相关的特征应将positive_score_impact
设置为false
(默认为true
)。这将由rank_feature
查询使用,以修改评分公式,使得得分随着特征值的增加而减少,而不是增加。例如,在网络搜索中,URL长度是一个常用的特征,它与得分呈负相关。
排名特征字段类型
edit一个 rank_features
字段可以索引数值特征向量,以便在查询中使用 rank_feature
查询时提升文档。
它类似于rank_feature
数据类型,但在特征列表稀疏的情况下更适合,因此为每个特征添加一个字段到映射中是不合理的。
PUT my-index-000001 { "mappings": { "properties": { "topics": { "type": "rank_features" }, "negative_reviews" : { "type": "rank_features", "positive_score_impact": false } } } } PUT my-index-000001/_doc/1 { "topics": { "politics": 20, "economics": 50.8 }, "negative_reviews": { "1star": 10, "2star": 100 } } PUT my-index-000001/_doc/2 { "topics": { "politics": 5.2, "sports": 80.1 }, "negative_reviews": { "1star": 1, "2star": 10 } } GET my-index-000001/_search { "query": { "rank_feature": { "field": "topics.politics" } } } GET my-index-000001/_search { "query": { "rank_feature": { "field": "negative_reviews.1star" } } } GET my-index-000001/_search { "query": { "term": { "topics": "economics" } } }
Rank features 字段必须使用 |
|
需要声明与得分负相关的特征排名 |
|
排序特征字段必须是一个带有字符串键和严格正数值的哈希 |
|
此查询根据文档与“政治”主题的相关程度对文档进行排名。 |
|
此查询根据文档收到的“1星”评论数量对其进行反向排名。 |
|
此查询返回在“topics”字段中存储“economics”特征的文档。 |
rank_features
字段仅支持单值特征和严格正值。多值字段以及零或负值将被拒绝。
rank_features
字段不支持排序或聚合,并且只能使用 rank_feature
或 term
查询进行查询。
term
查询在 rank_features
字段上的评分是通过将匹配的存储特征值与提供的 boost
相乘来计算的。
rank_features
字段仅保留9个有效位用于精度,这相当于大约0.4%的相对误差。
与得分负相关的特征应将positive_score_impact
设置为false
(默认为true
)。这将由rank_feature
查询用于修改评分公式,使得得分随着特征值的增加而减少,而不是增加。
即时搜索字段类型
editThe search_as_you_type
字段类型是一种类似于文本的字段,它经过优化,可以提供开箱即用的支持,用于处理服务于“边输入边搜索”用例的查询。它会创建一系列子字段,这些子字段经过分析以索引术语,这些术语可以通过部分匹配整个索引文本值的查询进行高效匹配。支持前缀补全(即匹配从输入开头开始的术语)和中间补全(即匹配输入中任何位置的术语)。
当向映射中添加此类型的字段时
PUT my-index-000001 { "mappings": { "properties": { "my_field": { "type": "search_as_you_type" } } } }
这将创建以下字段
|
按照映射中的配置进行分析。如果未配置分析器,则使用索引的默认分析器 |
|
将 |
|
将 |
|
将 |
子字段中的平铺大小可以通过 max_shingle_size
映射参数进行配置。默认值为 3,该参数的有效值为 2 到 4 之间的整数。将为每个从 2 到 max_shingle_size
的平铺大小创建平铺子字段。my_field._index_prefix
子字段在构建自己的分析器时,总是使用具有 max_shingle_size
的平铺子字段的分析器。
增加 max_shingle_size
将提高对包含更多连续词的查询的匹配度,但代价是索引大小会变大。默认的 max_shingle_size
通常已经足够。
相同的输入文本会自动索引到这些字段中的每一个,当索引文档具有根字段my_field
的值时,它们会使用不同的分析链。
PUT my-index-000001/_doc/1?refresh { "my_field": "quick brown fox jump lazy dog" }
实现搜索即用型用例的最有效查询方式通常是类型为multi_match
的查询,其类型为bool_prefix
,目标为根search_as_you_type
字段及其子字段。这可以匹配查询词的任何顺序,但如果它们在子字段中按顺序包含这些词,则会对文档进行更高的评分。
GET my-index-000001/_search { "query": { "multi_match": { "query": "brown f", "type": "bool_prefix", "fields": [ "my_field", "my_field._2gram", "my_field._3gram" ] } } }
{ "took" : 44, "timed_out" : false, "_shards" : { "total" : 1, "successful" : 1, "skipped" : 0, "failed" : 0 }, "hits" : { "total" : { "value" : 1, "relation" : "eq" }, "max_score" : 0.8630463, "hits" : [ { "_index" : "my-index-000001", "_id" : "1", "_score" : 0.8630463, "_source" : { "my_field" : "quick brown fox jump lazy dog" } } ] } }
要搜索严格按顺序匹配查询词的文档,或使用短语查询的其他属性进行搜索,请在根字段上使用match_phrase_prefix
查询。如果最后一个词应完全匹配,而不是作为前缀,也可以使用match_phrase
查询。使用短语查询可能不如使用match_bool_prefix
查询高效。
GET my-index-000001/_search { "query": { "match_phrase_prefix": { "my_field": "brown f" } } }
特定于 search_as_you_type
字段的参数
edit以下参数在映射中被接受用于search_as_you_type
字段,并且是此字段类型特有的
-
max_shingle_size
-
(可选,整数) 创建的最大shingle大小。有效值为
2
(包含)到4
(包含)。默认为3
。为每个介于
2
和此值之间的整数创建一个子字段。例如,值为3
会创建两个子字段:my_field._2gram
和my_field._3gram
更多的子字段可以实现更具体的查询,但会增加索引大小。
作为文本字段的字段类型的参数
edit由于search_as_you_type
字段的文本特性,映射中接受以下参数,并且它们在配置text
数据类型字段时的行为类似。除非另有说明,这些选项以相同的方式配置根字段的子字段。
-
analyzer
-
用于
text
字段的分析器,在索引时和搜索时都应使用(除非被search_analyzer
覆盖)。默认值为默认索引分析器,或标准
分析器。 -
index
-
字段是否可搜索?接受
true
(默认)或false
。 -
index_options
-
应将哪些信息存储在索引中,以便用于搜索和突出显示。默认为
positions
。 -
norms
-
Whether field-length should be taken into account when scoring queries.
Accepts
true
orfalse
. This option configures the root field and shingle subfields, where its default istrue
. It does not configure the prefix subfield, where it isfalse
. -
store
-
字段值是否应与
_source
字段分开存储和检索。接受true
或false
(默认)。此选项仅配置根字段,并不配置任何子字段。 -
search_analyzer
-
在搜索时应使用的
分析器
文本
字段。默认为分析器
设置。 -
search_quote_analyzer
-
在搜索时遇到短语时应使用的
分析器
。默认为search_analyzer
设置。 -
similarity
-
使用哪种评分算法或相似度。默认为
BM25
。 -
term_vector
-
是否应为该字段存储词向量。默认为
否
。此选项配置根字段和子字段,但不配置前缀子字段。
前缀查询的优化
edit当对根字段或其任何子字段进行 prefix
查询时,查询将被重写为对 ._index_prefix
子字段的 term
查询。这比通常在文本字段上进行的 prefix
查询更高效,因为每个分词的前缀长度达到一定长度时,会直接作为 ._index_prefix
子字段中的词项进行索引。
对 ._index_prefix
子字段的分析器稍微修改了构建 shingles 的行为,以便在字段值末尾的术语通常不会作为 shingles 生成时,也会索引这些术语的前缀。例如,如果将值 quick brown fox
索引到一个 search_as_you_type
字段中,并且 max_shingle_size
为 3,则 brown fox
和 fox
的前缀也会被索引到 ._index_prefix
子字段中,即使它们没有出现在 ._3gram
子字段中。这允许完成字段输入中的所有术语。
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
search_as_you_type
字段在其默认配置中支持 合成 _source
。
语义文本字段类型
edit此功能处于测试阶段,可能会发生变化。设计和代码不如正式发布的功能成熟,并且是按原样提供的,不提供任何保证。测试功能不受正式发布功能的支持服务级别协议的约束。
The semantic_text
字段类型使用推理端点自动为文本内容生成嵌入。
长段落会被自动分块为较小的部分,以实现对更大文本语料库的处理。
The semantic_text
字段类型指定将用于生成嵌入的推理端点标识符。
您可以通过使用 Create inference API 来创建推理端点。
此字段类型和 semantic
查询 类型使得对您的数据进行语义搜索变得更加简单。
使用semantic_text
,您不需要指定如何生成数据的嵌入,或如何对其进行索引。推理端点会自动确定要使用的嵌入生成、索引和查询。
PUT my-index-000001 { "mappings": { "properties": { "inference_field": { "type": "semantic_text", "inference_id": "my-elser-endpoint" } } } }
使用semantic_text的推荐方式是为摄取和搜索设置专门的推理端点。
这确保了搜索速度不受摄取工作负载的影响,反之亦然。
在为两者创建专门的推理端点后,您可以在为使用semantic_text
字段的索引设置索引映射时,使用inference_id
和search_inference_id
参数来引用它们。
PUT my-index-000002 { "mappings": { "properties": { "inference_field": { "type": "semantic_text", "inference_id": "my-elser-endpoint-for-ingest", "search_inference_id": "my-elser-endpoint-for-search" } } } }
semantic_text
字段的参数
edit推理端点验证
edit在创建映射时,inference_id
不会被验证,而是在将文档索引到索引中时进行验证。
当第一个文档被索引时,inference_id
将用于为该字段生成底层索引结构。
删除推理端点将导致在定义了semantic_text
字段且将该推理端点作为其inference_id
的索引上,文档摄取和语义查询失败。
尝试删除一个在semantic_text
字段上使用的推理端点将导致错误。
自动文本分块
edit推理端点对它们可以处理的文本量有限制。
为了允许在语义搜索中使用大量文本,semantic_text
会自动生成较小的段落(如果需要),称为块。
每个块将包含文本子段落及其生成的相应嵌入。 在查询时,每个文档的各个段落将自动进行搜索,并使用最相关的段落来计算得分。
文档被分割成250个词的部分,每部分之间有100个词的重叠,这样每个部分都与前一部分共享100个词。 这种重叠确保了连续性,并防止输入文本中的重要上下文信息因硬性分隔而丢失。
semantic_text
结构
edit一旦文档被摄取,semantic_text
字段将具有以下结构:
"inference_field": { "text": "these are not the droids you're looking for", "inference": { "inference_id": "my-elser-endpoint", "model_settings": { "task_type": "sparse_embedding" }, "chunks": [ { "text": "these are not the droids you're looking for", "embeddings": { (...) } } ] } }
该字段将变为一个对象结构,以容纳原始文本和推理结果。 |
|
用于生成嵌入的 |
|
模型设置,包括任务类型和维度/相似性(如果适用)。 |
|
推理结果将按块分组,每个块都有其对应的文本和嵌入。 |
请参考本教程以了解更多关于使用semantic_text
和semantic
查询进行语义搜索的信息。
自定义 semantic_text
索引
editsemantic_text
使用基于指定推理端点的默认值来索引数据。它使您能够通过提供自动推理和专用查询来快速启动语义搜索,而无需提供进一步的详细信息。
如果您想自定义数据索引,请使用
sparse_vector
或 dense_vector
字段类型,并创建一个包含
推理处理器 的摄取管道来生成嵌入。
本教程 将带您了解整个过程。在这些情况下 - 当您使用 sparse_vector
或 dense_vector
字段类型而不是
semantic_text
字段类型来自定义索引时 - 不支持使用
semantic_query
来查询字段数据。
更新到 semantic_text
字段
edit不支持对包含semantic_text
字段的索引使用脚本进行更新。
即使脚本针对的是非semantic_text
字段,当索引包含semantic_text
字段时,更新也会失败。
copy_to
支持
editsemantic_text
字段类型可以是 copy_to
字段的目标。这意味着您可以使用单个 semantic_text
字段来收集其他字段的值以进行语义搜索。每个值的嵌入是分别计算的;每个字段值在结果嵌入中是单独的一组块。
这给批量请求和更新包含semantic_text
字段的文档的摄取管道施加了限制。
在这些情况下,所有复制到semantic_text
字段的字段,包括semantic_text
字段值,都必须有一个值,以确保每个嵌入都能被正确计算。
例如,以下映射:
PUT test-index { "mappings": { "properties": { "infer_field": { "type": "semantic_text", "inference_id": "my-elser-endpoint" }, "source_field": { "type": "text", "copy_to": "infer_field" } } } }
需要以下批量更新请求以确保 infer_field
被正确更新:
PUT test-index/_bulk {"update": {"_id": "1"}} {"doc": {"infer_field": "updated inference field", "source_field": "updated source field"}}
请注意,在批量请求中,semantic_text
字段和源字段都被更新了。
限制
editsemantic_text
字段类型有以下限制:
形状字段类型
editThe shape
数据类型便于对任意 x, y
笛卡尔形状(如矩形和多边形)进行索引和搜索。它可以用于索引和查询坐标落在二维平面坐标系中的几何图形。
您可以使用形状查询来查询此类文档。
映射选项
edit与geo_shape
字段类型类似,shape
字段映射将
GeoJSON或Well-Known Text
(WKT)几何对象映射到形状类型。要启用它,用户必须显式地将字段映射到形状类型。
Option | Description | Default |
---|---|---|
|
可选地定义如何解释多边形/多边形的顶点顺序。此参数定义了两种坐标系规则(右手或左手)中的一种,每种规则可以通过三种不同的方式指定。1. 右手规则: |
|
|
如果为真,格式错误的GeoJSON或WKT形状将被忽略。如果为假(默认),格式错误的GeoJSON和WKT形状将抛出异常并拒绝整个文档。 |
|
|
如果为 |
|
|
如果 |
|
索引方法
edit与geo_shape
类似,shape
字段类型通过将几何图形分解为三角网格,并将每个三角形索引为BKD树中的一个7维点来进行索引。
提供给索引器的坐标是单精度浮点值,因此该字段保证了与Java虚拟机提供的相同的精度(通常为1E-38
)。对于多边形/多重多边形,镶嵌器的性能主要取决于定义几何图形的顶点数量。
重要提示
CONTAINS
关系查询 - 使用 contains
定义的 relation
的 shape
查询在 ElasticSearch 7.5.0 或更高版本创建的索引中受支持。
示例
editPUT /example { "mappings": { "properties": { "geometry": { "type": "shape" } } } }
此映射定义将几何字段映射到形状类型。索引器使用单精度浮点数来表示顶点值,因此精度与Java虚拟机提供的float
值的精度大致相同(通常为1E-38)。
输入结构
edit形状可以使用GeoJSON 或熟知文本 (WKT)格式表示。下表提供了GeoJSON和WKT到Elasticsearch类型的映射:
GeoJSON Type | WKT Type | Elasticsearch Type | Description |
---|---|---|---|
|
|
|
一个单一的 |
|
|
|
给定两个或更多点的一条任意线。 |
|
|
|
一个闭合的多边形,其第一个和最后一个点必须匹配,因此需要 |
|
|
|
一组未连接但可能相关的点。 |
|
|
|
一组独立的线串。 |
|
|
|
一个由多个独立多边形组成的数组。 |
|
|
|
一个形状集合,类似于 |
|
|
|
一个边界矩形,或信封,通过仅指定左上角和右下角点来指定。 |
对于所有类型,都需要同时包含内部字段type
和coordinates
。
在GeoJSON和WKT中,以及因此Elasticsearch中,坐标数组内的正确坐标顺序是(X, Y)。这与许多地理空间API(例如,geo_shape
)通常使用的俗称纬度、经度(Y, X)顺序不同。
点是笛卡尔坐标系中的一个单一坐标 x, y
。它可能代表虚拟世界或投影空间中某个感兴趣项目的位置。以下是GeoJSON中一个点的示例。
POST /example/_doc { "location" : { "type" : "point", "coordinates" : [-377.03653, 389.897676] } }
以下是一个WKT中点的示例:
POST /example/_doc { "location" : "POINT (-377.03653 389.897676)" }
由两个或更多位置的数组定义的linestring
。通过仅指定两个点,linestring
将表示一条直线。指定两个以上的点将创建任意路径。以下是GeoJSON中LineString的一个示例。
POST /example/_doc { "location" : { "type" : "linestring", "coordinates" : [[-377.03653, 389.897676], [-377.009051, 389.889939]] } }
以下是WKT中LineString的一个示例:
POST /example/_doc { "location" : "LINESTRING (-377.03653 389.897676, -377.009051 389.889939)" }
多边形由一系列点列表定义。每个(外部)列表中的第一个和最后一个点必须是相同的(多边形必须是封闭的)。以下是GeoJSON中多边形的一个示例。
POST /example/_doc { "location" : { "type" : "polygon", "coordinates" : [ [ [1000.0, -1001.0], [1001.0, -1001.0], [1001.0, -1000.0], [1000.0, -1000.0], [1000.0, -1001.0] ] ] } }
以下是WKT中多边形的一个示例:
POST /example/_doc { "location" : "POLYGON ((1000.0 -1001.0, 1001.0 -1001.0, 1001.0 -1000.0, 1000.0 -1000.0, 1000.0 -1001.0))" }
第一个数组表示多边形的外边界,其他数组表示内部形状(“孔”)。以下是一个带有孔的多边形的GeoJSON示例:
POST /example/_doc { "location" : { "type" : "polygon", "coordinates" : [ [ [1000.0, -1001.0], [1001.0, -1001.0], [1001.0, -1000.0], [1000.0, -1000.0], [1000.0, -1001.0] ], [ [1000.2, -1001.2], [1000.8, -1001.2], [1000.8, -1001.8], [1000.2, -1001.8], [1000.2, -1001.2] ] ] } }
以下是一个带有孔洞的多边形的WKT示例:
POST /example/_doc { "location" : "POLYGON ((1000.0 1000.0, 1001.0 1000.0, 1001.0 1001.0, 1000.0 1001.0, 1000.0 1000.0), (1000.2 1000.2, 1000.8 1000.2, 1000.8 1000.8, 1000.2 1000.8, 1000.2 1000.2))" }
重要提示: WKT 不强制规定顶点的特定顺序。 GeoJSON 规定外多边形必须是逆时针方向,内部形状必须是顺时针方向, 这与开放地理空间联盟(OGC) 简单要素访问 规范中关于顶点顺序的规定一致。
默认情况下,Elasticsearch 期望顶点按逆时针(右手定则)顺序排列。如果数据按顺时针顺序(左手定则)提供,用户可以在字段映射中或作为文档提供的参数中更改 orientation
参数。
以下是一个覆盖文档中orientation
参数的示例:
POST /example/_doc { "location" : { "type" : "polygon", "orientation" : "clockwise", "coordinates" : [ [ [1000.0, 1000.0], [1000.0, 1001.0], [1001.0, 1001.0], [1001.0, 1000.0], [1000.0, 1000.0] ] ] } }
以下是GeoJSON点列表的一个示例:
POST /example/_doc { "location" : { "type" : "multipoint", "coordinates" : [ [1002.0, 1002.0], [1003.0, 2000.0] ] } }
以下是一个WKT点列表的示例:
POST /example/_doc { "location" : "MULTIPOINT (1002.0 2000.0, 1003.0 2000.0)" }
以下是一个GeoJSON线串列表的示例:
POST /example/_doc { "location" : { "type" : "multilinestring", "coordinates" : [ [ [1002.0, 200.0], [1003.0, 200.0], [1003.0, 300.0], [1002.0, 300.0] ], [ [1000.0, 100.0], [1001.0, 100.0], [1001.0, 100.0], [1000.0, 100.0] ], [ [1000.2, 100.2], [1000.8, 100.2], [1000.8, 100.8], [1000.2, 100.8] ] ] } }
以下是WKT线串列表的一个示例:
POST /example/_doc { "location" : "MULTILINESTRING ((1002.0 200.0, 1003.0 200.0, 1003.0 300.0, 1002.0 300.0), (1000.0 100.0, 1001.0 100.0, 1001.0 100.0, 1000.0 100.0), (1000.2 0.2, 1000.8 100.2, 1000.8 100.8, 1000.2 100.8))" }
以下是一个包含GeoJSON多边形列表的示例(第二个多边形包含一个洞):
POST /example/_doc { "location" : { "type" : "multipolygon", "coordinates" : [ [ [[1002.0, 200.0], [1003.0, 200.0], [1003.0, 300.0], [1002.0, 300.0], [1002.0, 200.0]] ], [ [[1000.0, 200.0], [1001.0, 100.0], [1001.0, 100.0], [1000.0, 100.0], [1000.0, 100.0]], [[1000.2, 200.2], [1000.8, 100.2], [1000.8, 100.8], [1000.2, 100.8], [1000.2, 100.2]] ] ] } }
以下是一个WKT多边形列表的示例(第二个多边形包含一个洞):
POST /example/_doc { "location" : "MULTIPOLYGON (((1002.0 200.0, 1003.0 200.0, 1003.0 300.0, 1002.0 300.0, 102.0 200.0)), ((1000.0 100.0, 1001.0 100.0, 1001.0 100.0, 1000.0 100.0, 1000.0 100.0), (1000.2 100.2, 1000.8 100.2, 1000.8 100.8, 1000.2 100.8, 1000.2 100.2)))" }
以下是一个包含多个GeoJSON几何对象的示例:
POST /example/_doc { "location" : { "type": "geometrycollection", "geometries": [ { "type": "point", "coordinates": [1000.0, 100.0] }, { "type": "linestring", "coordinates": [ [1001.0, 100.0], [1002.0, 100.0] ] } ] } }
以下是一个WKT几何对象集合的示例:
POST /example/_doc { "location" : "GEOMETRYCOLLECTION (POINT (1000.0 100.0), LINESTRING (1001.0 100.0, 1002.0 100.0))" }
信封
editElasticsearch 支持一种 envelope
类型,它由形状的左上角和右下角的坐标组成,以表示边界矩形,格式为 [[minX, maxY], [maxX, minY]]
:
POST /example/_doc { "location" : { "type" : "envelope", "coordinates" : [ [1000.0, 100.0], [1001.0, 100.0] ] } }
以下是使用WKT BBOX格式的信封示例:
注意: WKT 规范要求以下顺序:minLon, maxLon, maxLat, minLat。
POST /example/_doc { "location" : "BBOX (1000.0, 1002.0, 2000.0, 1000.0)" }
排序和检索索引形状
edit由于形状的复杂输入结构和索引表示,目前无法直接对形状进行排序或检索其字段。shape
值只能通过 _source
字段检索。
稀疏向量场类型
edit一个 sparse_vector
字段可以索引特征和权重,以便在带有 sparse_vector
的查询中用于查询文档。
该字段还可以与遗留的 text_expansion
查询一起使用。
sparse_vector
是应与 ELSER 映射 一起使用的字段类型。
PUT my-index { "mappings": { "properties": { "text.tokens": { "type": "sparse_vector" } } } }
请参阅使用ELSER进行语义搜索,了解如何使用ELSER向sparse_vector
映射字段添加文档的完整示例。
多值稀疏向量
edit当为稀疏向量传入值数组时,会选择名称相似的特征的最大值。
论文《Adapting Learned Sparse Retrieval for Long Documents》(https://arxiv.org/pdf/2305.18494.pdf)对此进行了更详细的讨论。 总之,研究结果表明,表示聚合通常优于分数聚合。
在需要使用重叠特征名称的情况下,应将它们分别存储或使用嵌套字段。
下面是一个传递具有重叠特征名称的文档的示例。
考虑在这个示例中,存在两个类别用于正面情感和负面情感。
然而,为了检索的目的,我们还需要整体影响,而不是特定的情感。
在示例中,impact
存储为一个多值稀疏向量,并且只存储重叠名称的最大值。
更具体地说,这里的最终 GET
查询返回一个 _score
约为 1.2(即 max(impact.delicious[0], impact.delicious[1])
,由于我们有一个相对误差为 0.4%,因此是近似的,如下所述)
PUT my-index-000001 { "mappings": { "properties": { "text": { "type": "text", "analyzer": "standard" }, "impact": { "type": "sparse_vector" }, "positive": { "type": "sparse_vector" }, "negative": { "type": "sparse_vector" } } } } POST my-index-000001/_doc { "text": "I had some terribly delicious carrots.", "impact": [{"I": 0.55, "had": 0.4, "some": 0.28, "terribly": 0.01, "delicious": 1.2, "carrots": 0.8}, {"I": 0.54, "had": 0.4, "some": 0.28, "terribly": 2.01, "delicious": 0.02, "carrots": 0.4}], "positive": {"I": 0.55, "had": 0.4, "some": 0.28, "terribly": 0.01, "delicious": 1.2, "carrots": 0.8}, "negative": {"I": 0.54, "had": 0.4, "some": 0.28, "terribly": 2.01, "delicious": 0.02, "carrots": 0.4} } GET my-index-000001/_search { "query": { "term": { "impact": { "value": "delicious" } } } }
sparse_vector
字段不能包含在 Elasticsearch 版本 8.0 到 8.10 之间创建的索引中
sparse_vector
字段仅支持严格正值。
负值将被拒绝。
sparse_vector
字段不支持 分析器、查询、排序或聚合。
它们只能用于专门的查询中。
在这些字段上推荐的查询是 sparse_vector
查询。
它们也可以用于遗留的 text_expansion
查询中。
sparse_vector
字段仅保留9位有效位用于精度,这相当于大约0.4%的相对误差。
文本类型家族
edit文本系列包括以下字段类型:
-
text
,传统的字段类型,用于全文内容,例如电子邮件的正文或产品的描述。 -
match_only_text
,text
的空间优化变体,禁用评分并在需要位置的查询上执行较慢。它最适合用于索引日志消息。
文本字段类型
edit用于索引全文值的字段,例如电子邮件的正文或产品的描述。这些字段是分析过的
,也就是说,它们在索引之前通过一个分析器被转换为单个术语的列表。分析过程允许Elasticsearch在每个全文字段中搜索单个单词内。文本字段不用于排序,也很少用于聚合(尽管显著文本聚合是一个值得注意的例外)。
text
字段最适合用于非结构化但人类可读的内容。如果您需要索引非结构化的机器生成内容,请参阅
映射非结构化内容。
如果你需要索引结构化内容,如电子邮件地址、主机名、状态码或标签,那么你可能应该使用一个keyword
字段。
下面是一个文本字段映射的示例:
PUT my-index-000001 { "mappings": { "properties": { "full_name": { "type": "text" } } } }
文本字段的参数
edit以下参数被text
字段接受:
用于 |
|
是否应在刷新时急切加载全局序数?接受 |
|
该字段是否可以使用内存中的fielddata进行排序、聚合或脚本操作?接受 |
|
专家设置,允许在启用 |
|
多字段允许将相同的字符串值以多种方式进行索引,以满足不同的目的,例如一个字段用于搜索,另一个多字段用于排序和聚合,或者使用不同的分析器对相同的字符串值进行分析。 |
|
字段是否应可搜索?接受 |
|
为了搜索和突出显示的目的,索引中应存储哪些信息。
默认为 |
|
如果启用,长度在2到5个字符之间的术语前缀将被索引到一个单独的字段中。这使得前缀搜索能够更高效地运行,但代价是索引更大。 |
|
如果启用,双词组合(shingles)将被索引到一个单独的字段中。这使得精确短语查询(无偏差)能够更高效地运行,但代价是索引更大。请注意,当停用词未被移除时,此功能效果最佳,因为包含停用词的短语将不会使用辅助字段,而是回退到标准短语查询。接受 |
|
是否应在评分查询时考虑字段长度。
接受 |
|
在字符串数组中的每个元素之间应插入的假词位置的数量。默认为分析器上配置的 |
|
字段值是否应与 |
|
在搜索时应使用的 |
|
在搜索时遇到短语时应使用的 |
|
使用哪种评分算法或相似度。默认为 |
|
是否应为该字段存储词向量。默认为 |
|
字段的元数据。 |
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
text
字段支持 synthetic _source
,如果它们有一个支持 synthetic _source
的 keyword
子字段,或者如果 text
字段将 store
设置为 true
。无论哪种方式,它可能没有 copy_to
。
如果使用子keyword
字段,则值的排序方式与keyword
字段的值排序方式相同。默认情况下,这意味着排序时会去除重复项。因此:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "text": { "type": "text", "fields": { "raw": { "type": "keyword" } } } } } } PUT idx/_doc/1 { "text": [ "the quick brown fox", "the quick brown fox", "jumped over the lazy dog" ] }
将变为:
{ "text": [ "jumped over the lazy dog", "the quick brown fox" ] }
重新排序文本字段可能会影响短语
和跨度查询。有关更多详细信息,请参阅关于
position_increment_gap
的讨论。您
可以通过确保短语查询中的slop
参数
低于position_increment_gap
来避免这种情况。这是默认设置。
如果 text
字段将 store
设置为 true,则顺序和重复项将被保留。
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "text": { "type": "text", "store": true } } } } PUT idx/_doc/1 { "text": [ "the quick brown fox", "the quick brown fox", "jumped over the lazy dog" ] }
将变为:
{ "text": [ "the quick brown fox", "the quick brown fox", "jumped over the lazy dog" ] }
fielddata
映射参数
edittext
字段默认是可搜索的,但默认情况下不可用于聚合、排序或脚本。如果你尝试对 text
字段进行排序、聚合或使用脚本访问其值,你会看到一个异常,指示默认情况下在文本字段上禁用了字段数据。要在内存中加载字段数据,请在你的字段上设置 fielddata=true
。
在内存中加载字段数据可能会消耗大量内存。
字段数据是访问全文字段中分析后的标记以进行聚合、排序或脚本的唯一方式。例如,一个全文字段如New York
会被分析为new
和york
。要对这些标记进行聚合,需要字段数据。
启用fielddata前的注意事项
edit通常情况下,在文本字段上启用fielddata是没有意义的。Field data存储在堆内存中,使用field data缓存,因为计算它是非常昂贵的。计算field data可能会导致延迟峰值,并且增加堆内存使用是集群性能问题的一个原因。
大多数想要对文本字段进行更多操作的用户会使用多字段映射,
通过同时拥有一个用于全文搜索的text
字段,以及一个
未分析的用于聚合的keyword
字段,如下所示:
在text
字段上启用fielddata
edit您可以使用更新映射 API在现有的text
字段上启用fielddata,如下所示:
fielddata_frequency_filter
映射参数
edit字段数据过滤可以用于减少加载到内存中的词项数量,从而减少内存使用。词项可以通过频率进行过滤:
频率过滤器允许你只加载文档频率落在min
和max
值之间的术语,这可以表示为绝对数(当数字大于1.0时)或百分比(例如0.01
是1%
,1.0
是100%
)。频率是按每个分段计算的。百分比基于具有该字段值的文档数量,而不是分段中的所有文档。
可以通过指定段落应包含的最小文档数量来完全排除小段落,使用 min_segment_size
:
PUT my-index-000001 { "mappings": { "properties": { "tag": { "type": "text", "fielddata": true, "fielddata_frequency_filter": { "min": 0.001, "max": 0.1, "min_segment_size": 500 } } } } }
仅匹配文本字段类型
edit一种text
的变体,它在空间效率上进行了权衡,牺牲了评分和位置查询的效率。该字段实际上以与仅索引文档的text
字段(index_options: docs
)并禁用规范(norms: false
)相同的方式存储数据。术语查询的执行速度与text
字段一样快,甚至更快,然而需要位置的查询,如match_phrase
查询,执行速度较慢,因为它们需要查看_source
文档以验证短语是否匹配。所有查询返回的常量分数等于1.0。
分析是不可配置的:文本总是使用默认分析器进行分析(默认情况下为standard
)。
跨度查询在此字段中不受支持,请改用区间查询,或者如果您绝对需要跨度查询,请使用text
字段类型。
除此之外,match_only_text
支持与 text
相同的查询。并且与 text
一样,它不支持排序,并且仅对聚合提供有限的支持。
PUT logs { "mappings": { "properties": { "@timestamp": { "type": "date" }, "message": { "type": "match_only_text" } } } }
仅匹配文本字段的参数
edit接受的映射参数如下:
Token 计数字段类型
edit类型为 token_count
的字段实际上是一个 integer
字段,它接受字符串值,对其进行分析,然后索引字符串中的标记数量。
例如:
PUT my-index-000001 { "mappings": { "properties": { "name": { "type": "text", "fields": { "length": { "type": "token_count", "analyzer": "standard" } } } } } } PUT my-index-000001/_doc/1 { "name": "John Smith" } PUT my-index-000001/_doc/2 { "name": "Rachel Alice Williams" } GET my-index-000001/_search { "query": { "term": { "name.length": 3 } } }
字段 |
|
字段 |
|
此查询仅匹配包含 |
token_count
字段的参数
edit以下参数被token_count
字段接受:
用于分析字符串值的分析器。必需。为了获得最佳性能,请使用不带标记过滤器的分析器。 |
|
|
指示是否应计算位置增量。
如果不想计算由分析器过滤器(如 |
字段是否应以列步长的方式存储在磁盘上,以便以后可以用于排序、聚合或脚本?接受 |
|
字段是否可搜索?接受 |
|
接受与字段相同 |
|
字段值是否应与 |
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
token_count
字段在其默认配置中支持 synthetic _source
。
无符号长字段类型
edit无符号长整型是一种数值字段类型,表示一个无符号的64位整数,其最小值为0,最大值为264-1
(从0到18446744073709551615,包含两端)。
PUT my_index { "mappings": { "properties": { "my_counter": { "type": "unsigned_long" } } } }
无符号长整型可以以数字或字符串形式进行索引, 表示范围在 [0, 18446744073709551615] 内的整数值。 它们不能有小数部分。
POST /my_index/_bulk?refresh {"index":{"_id":1}} {"my_counter": 0} {"index":{"_id":2}} {"my_counter": 9223372036854775808} {"index":{"_id":3}} {"my_counter": 18446744073709551614} {"index":{"_id":4}} {"my_counter": 18446744073709551615}
术语查询接受任何数字形式或字符串形式的数字。
GET /my_index/_search { "query": { "term" : { "my_counter" : 18446744073709551615 } } }
范围查询条件可以包含带有小数部分的值。
在这种情况下,Elasticsearch 会将它们转换为整数值:
gte
和 gt
条件会向上取整,包含边界值,
而 lt
和 lte
范围会向下取整,包含边界值。
建议将范围作为字符串传递,以确保它们在解析时不会丢失任何精度。
GET /my_index/_search { "query": { "range" : { "my_counter" : { "gte" : "9223372036854775808", "lte" : "18446744073709551615" } } } }
排序值
edit对于在unsigned_long
字段上进行排序的查询,
对于特定文档,如果该文档的值在long值范围内,Elasticsearch会返回类型为long
的排序值,
如果该值超出此范围,则返回类型为BigInteger
的排序值。
REST客户端需要能够处理JSON中的大整数值,以正确支持此字段类型。
GET /my_index/_search { "query": { "match_all" : {} }, "sort" : {"my_counter" : "desc"} }
存储字段
edit一个存储的字段 unsigned_long
被存储并以 String
形式返回。
聚合
edit对于terms
聚合,类似于排序值,使用Long
或BigInteger
值。对于其他聚合,值被转换为double
类型。
脚本值
edit默认情况下,unsigned_long
字段的脚本值会以 Java 有符号 Long
的形式返回,这意味着大于 Long.MAX_VALUE
的值会显示为负值。您可以使用 Long.compareUnsigned(long, long)
、Long.divideUnsigned(long, long)
和 Long.remainderUnsigned(long, long)
来正确处理这些值。
例如,下面的脚本返回计数器除以10的值。
GET /my_index/_search { "query": { "match_all" : {} }, "script_fields": { "count10" : { "script": { "source": "Long.divideUnsigned(doc['my_counter'].value, 10)" } } } }
或者,您可以通过使用字段 API 将无符号长整型视为 BigInteger
在您的脚本中。例如,此脚本
将 my_counter
视为 BigInteger
,默认值为 BigInteger.ZERO
:
"script": { "source": "field('my_counter').asBigInteger(BigInteger.ZERO)" }
对于需要返回浮点数或双精度数值的脚本,您可以将BigInteger
值进一步转换为双精度或浮点数:
GET /my_index/_search { "query": { "script_score": { "query": {"match_all": {}}, "script": { "source": "field('my_counter').asBigInteger(BigInteger.ZERO).floatValue()" } } } }
混合数值类型的查询
edit支持混合数值类型的搜索,其中一种是unsigned_long
,但不支持带有排序的查询。因此,在两个索引中对同一字段名称进行排序查询,其中一个索引中的字段类型为unsigned_long
,另一个索引中的字段类型为long
,不会产生正确的结果,必须避免这种情况。如果需要进行此类排序,可以使用基于脚本的排序来代替。
支持对几种数值类型进行聚合,其中一种是unsigned_long
。在这种情况下,值会被转换为double
类型。
版本字段类型
editversion
字段类型是 keyword
字段的一个专门化,用于处理软件版本值并支持它们的专用优先规则。优先级是根据 语义版本控制 的规则定义的,这意味着主要、次要和补丁版本部分按数值排序(例如 "2.1.0" < "2.4.1" < "2.11.2"),并且预发布版本在发布版本之前排序(例如 "1.0.0-alpha" < "1.0.0")。
您可以如下索引一个version
字段
PUT my-index-000001 { "mappings": { "properties": { "my_version": { "type": "version" } } } }
该字段提供了与常规关键词字段相同的搜索功能。例如,可以使用 match
或 term
查询进行精确匹配搜索,并支持前缀和通配符搜索。主要的好处是 range
查询将遵循语义版本排序,因此介于 "1.0.0" 和 "1.5.0" 之间的 range
查询将包括 "1.2.3" 版本,但不包括 "1.11.2" 版本。请注意,如果使用常规的 keyword
字段进行索引,排序将是按字母顺序排列的,结果会有所不同。
软件版本应遵循 语义版本控制规则 的架构和优先规则,但值得注意的是,允许使用多于或少于三个主要版本标识符(即“1.2”或“1.2.3.4”在严格的语义版本控制规则下不符合要求,但在此处被视为有效版本)。不符合语义版本定义的版本字符串(例如“1.2.alpha.4”)仍然可以被索引和作为精确匹配检索,但它们将按照常规字母顺序出现在所有有效版本之后。空字符串“”被视为无效,并排在所有有效版本之后,但在其他无效版本之前。
版本字段的参数
edit以下参数被version
字段接受:
字段的元数据。 |
限制
edit这种字段类型并不针对大量的通配符、正则表达式或模糊搜索进行优化。虽然这些类型的查询在此字段中可以工作,但如果您强烈依赖这些类型的查询,您应该考虑使用一个常规的 keyword
字段。
合成 _source
edit合成 _source
仅对 TSDB 索引(将 index.mode
设置为 time_series
的索引)正式发布。对于其他索引,合成 _source
处于技术预览阶段。技术预览中的功能可能会在未来的版本中更改或移除。Elastic 将努力修复任何问题,但技术预览中的功能不受官方 GA 功能支持 SLA 的约束。
version
字段在其默认配置中支持 synthetic _source
。
合成源可能会对version
字段值进行排序并去除重复项。例如:
PUT idx { "settings": { "index": { "mapping": { "source": { "mode": "synthetic" } } } }, "mappings": { "properties": { "versions": { "type": "version" } } } } PUT idx/_doc/1 { "versions": ["8.0.0-beta1", "8.5.0", "0.90.12", "2.6.1", "1.3.4", "1.3.4"] }
将变为:
{ "versions": ["0.90.12", "1.3.4", "2.6.1", "8.0.0-beta1", "8.5.0"] }