文章目录
ElasticSearch检索你的数据(四)
检索选中的字段
默认情况下每一个搜索的响应的hit
都包含文档的_source
字段,它是索引文档时提供的整个 JSON 对象。有两种推荐方法从搜索查询中检索选中字段“
- 使用
fields option
提取索引映射中存在的字段值 - 使用
_source option
来访问元数据
你可以同时使用这两种方法,但首选 fields option,因为它会同时查询文档数据和索引映射。在其他例子中,你可能使用其他的方式来检索数据。
filed option
使用fileds
参数在查询的响应中检索指定的字段。因为它参考索引映射,所以 fields 参数比直接引用 _source 有几个优点。具体来说,fields参数:
- 通过匹配映射类型的标准方式返回每一个值
- 接收
multi-fileds
和field alias
- 格式化时间与空间数据类型
- 检索运行时字段
- 在索引时可以通过脚本计算字段值并返回
其他映射选项也被考虑,包括ignore_above
、ignore_malformed
和null_value
。
fields
选项以Elasticsearch索引相匹配的方式返回值。对于标准的字段,这就意味着field
选项会在_source
字段中查找值,然后使用映射来解析与格式化他们。
搜索指定的字段
以下搜索请求使用 fields
参数检索 user.id
字段、所有以 http.response.
开头的字段和 @timestamp
字段的值。
用对象表示法,您可以为某些字段传递格式参数,以便为字段值应用自定义格式:
date
和date_nanos
字段接收date_format
Spatial fields
accept eithergeojson
forGeoJSON
(the default) orwkt
forWell Known Text
其他字段不支持格式化参数:
curl -X POST "localhost:9200/my-index-000001/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"fields": [
"user.id",
"http.response.*",
{
"field": "@timestamp",
"format": "epoch_millis"
}
],
"_source": false
}
'
响应总是返回一个数组
fields
响应总是为每个字段返回值数组,尽管只有在_source
中只有一个单独的值。这是因为ElasticSearch没有专门的数据类型,并且任何字段可以包含多个值。fields 参数也不保证以特定顺序返回数组值。有关更多背景信息,请参阅有关数组的映射文档。
响应中每个hit的fields部分都包含值的列表。因为field
参数不会拉取全文对象,只有叶子字段会被返回:
{
"hits" : {
"total" : {
"value" : 1,
"relation" : "eq"
},
"max_score" : 1.0,
"hits" : [
{
"_index" : "my-index-000001",
"_id" : "0",
"_score" : 1.0,
"_type" : "_doc",
"fields" : {
"user.id" : [
"kimchy"
],
"@timestamp" : [
"4098435132000"
],
"http.response.bytes": [
1070000
],
"http.response.status_code": [
200
]
}
}
]
}
}
检索嵌套字段
嵌套字段的字段响应与常规的字段响应是不同的。虽然常规对象字段内的叶值作为平面列表返回,但嵌套字段内的值被分组以保持原始嵌套数组内每个对象的独立性。对于嵌套字段数组中的每个条目,值将再次作为平面列表返回,除非父嵌套对象中有其他嵌套字段,在这种情况下,对更深的嵌套字段再次重复相同的过程。
给定以下映射,其中user是一个嵌套字段,索引以下文档并检索用户字段下的所有字段:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
"mappings": {
"properties": {
"group" : { "type" : "keyword" },
"user": {
"type": "nested",
"properties": {
"first" : { "type" : "keyword" },
"last" : { "type" : "keyword" }
}
}
}
}
}
'
curl -X PUT "localhost:9200/my-index-000001/_doc/1?refresh=true&pretty" -H 'Content-Type: application/json' -d'
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
'
curl -X POST "localhost:9200/my-index-000001/_search?pretty" -H 'Content-Type: application/json' -d'
{
"fields": ["*"],
"_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,
"_type": "_doc",
"fields": {
"group" : ["fans"],
"user": [{
"first": ["John"],
"last": ["Smith"],
},
{
"first": ["Alice"],
"last": ["White"],
}
]
}
}]
}
}
无论用于检索它们的模式如何,嵌套字段都将按其嵌套路径分组。例如,如果您只查询上一个示例中的 user.first 字段:
curl -X POST "localhost:9200/my-index-000001/_search?pretty" -H 'Content-Type: application/json' -d'
{
"fields": ["user.first"],
"_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,
"_type": "_doc",
"fields": {
"user": [{
"first": ["John"],
},
{
"first": ["Alice"],
}
]
}
}]
}
提取未映射的字段
默认情况下,fields
参数只返回别映射的字段的值。但是,ElasticSearch允许在_source
中存储未映射的字段,例如设置dynamic field mapping
为false
或者使用带有enabled:false
的字段。.这些选项禁用对象内容的解析和索引。
从_source
字段中检索一个对象中未映射的字段,在field
部分中使用include_ummapped
选项:
curl -X PUT "localhost:9200/my-index-000001?pretty" -H 'Content-Type: application/json' -d'
{
"mappings": {
"enabled": false
}
}
'
curl -X PUT "localhost:9200/my-index-000001/_doc/1?refresh=true&pretty" -H 'Content-Type: application/json' -d'
{
"user_id": "kimchy",
"session_data": {
"object": {
"some_field": "some_value"
}
}
}
'
curl -X POST "localhost:9200/my-index-000001/_search?pretty" -H 'Content-Type: application/json' -d'
{
"fields": [
"user_id",
{
"field": "session_data.object.*",
"include_unmapped" : true
}
],
"_source": false
}
'
响应将包含 session_data.object.* 路径下的字段结果,即使这些字段未映射。 user_id 字段也未映射,但不会包含在响应中,因为该字段模式的 include_unmapped 未设置为 true。
{
"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,
"_type" : "_doc",
"fields" : {
"session_data.object.some_field": [
"some_value"
]
}
}
]
}
}
_source
选项
您可以使用 _source 参数来选择返回源的哪些字段。这称为源过滤。
以下搜索 API 请求将 _source 请求正文参数设置为 false。文档来源不包含在响应中。
curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
"_source": false,
"query": {
"match": {
"user.id": "kimchy"
}
}
}
'
要仅返回源字段的子集,请在 _source 参数中指定通配符 (*) 模式。以下搜索 API 请求仅返回 obj 字段及其属性的源。
curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
"_source": "obj.*",
"query": {
"match": {
"user.id": "kimchy"
}
}
}
'
您还可以在 _source 字段中指定通配符模式数组。以下搜索 API 请求仅返回 obj1 和 obj2 字段及其属性的源。
curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
"_source": [ "obj1.*", "obj2.*" ],
"query": {
"match": {
"user.id": "kimchy"
}
}
}
'
为了更好地控制,您可以在 _source 参数中指定一个包含和排除模式数组的对象。
如果指定了包含属性,则仅返回与其模式之一匹配的源字段。您可以使用 excludes 属性从此子集中排除字段。
如果未指定 includes 属性,则返回整个文档源,不包括与 excludes 属性中的模式匹配的任何字段。
以下搜索 API 请求仅返回 obj1 和 obj2 字段及其属性的来源,不包括任何子description字段。
curl -X GET "localhost:9200/_search?pretty" -H 'Content-Type: application/json' -d'
{
"_source": {
"includes": [ "obj1.*", "obj2.*" ],
"excludes": [ "*.description" ]
},
"query": {
"term": {
"user.id": "kimchy"
}
}
}
'
跨集群搜索
跨集群搜索可以让一个搜索请求运行在一个或者多个远程的集群上。例如,你使用跨集群搜索去过滤和分析存储在不同数据中心上的日志数据。
提示:跨集群搜索请求必须是远程集群
支持的API
Search
Async search
Multi search
Search template
Multi search template
Field capabilities
跨集群所搜例子
远程集群设置
想要执行一个跨集群搜索,你必须至少要配置一个远程集群。
提示:如果你想要在云上跨集群搜索,你可以在ElasticSearch服务上配置远程集群。然后,您可以跨集群搜索并设置跨集群复制。
根据cluster update settting API
请求添加三个远程集群:cluster_one、cluster_two、cluster_three
。
curl -X PUT "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster": {
"remote": {
"cluster_one": {
"seeds": [
"127.0.0.1:9300"
]
},
"cluster_two": {
"seeds": [
"127.0.0.1:9301"
]
},
"cluster_three": {
"seeds": [
"127.0.0.1:9302"
]
}
}
}
}
}
'
在单独远程集群上执行搜索
根据以下search API
请求,在cluster_one
远程集群上搜索my-index-000001
索引:
curl -X GET "localhost:9200/cluster_one:my-index-000001/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
'
API响应为:
{
"took": 150,
"timed_out": false,
"_shards": {
"total": 1,
"successful": 1,
"failed": 0,
"skipped": 0
},
"_clusters": {
"total": 1,
"successful": 1,
"skipped": 0
},
"hits": {
"total" : {
"value": 1,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "cluster_one:my-index-000001",
"_type": "_doc",
"_id": "0",
"_score": 1,
"_source": {
"user": {
"id": "kimchy"
},
"message": "GET /search HTTP/1.1 200 1070000",
"http": {
"response":
{
"status_code": 200
}
}
}
}
]
}
}
在多个远程集群上执行搜索
根据以下查询请求在3个远程集群上执行my-index-000001
索引查询
- 你的本地集群
- 两个远程集群:
cluster_one、cluster_two
curl -X GET "localhost:9200/my-index-000001,cluster_one:my-index-000001,cluster_two:my-index-000001/_search?pretty" -H 'Content-Type: application/json' -d'
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"_source": ["user.id", "message", "http.response.status_code"]
}
'
API响应为:
{
"took": 150,
"timed_out": false,
"num_reduce_phases": 4,
"_shards": {
"total": 3,
"successful": 3,
"failed": 0,
"skipped": 0
},
"_clusters": {
"total": 3,
"successful": 3,
"skipped": 0
},
"hits": {
"total" : {
"value": 3,
"relation": "eq"
},
"max_score": 1,
"hits": [
{
"_index": "my-index-000001",
"_type": "_doc",
"_id": "0",
"_score": 2,
"_source": {
"user": {
"id": "kimchy"
},
"message": "GET /search HTTP/1.1 200 1070000",
"http": {
"response":
{
"status_code": 200
}
}
}
},
{
"_index": "cluster_one:my-index-000001",
"_type": "_doc",
"_id": "0",
"_score": 1,
"_source": {
"user": {
"id": "kimchy"
},
"message": "GET /search HTTP/1.1 200 1070000",
"http": {
"response":
{
"status_code": 200
}
}
}
},
{
"_index": "cluster_two:my-index-000001",
"_type": "_doc",
"_id": "0",
"_score": 1,
"_source": {
"user": {
"id": "kimchy"
},
"message": "GET /search HTTP/1.1 200 1070000",
"http": {
"response":
{
"status_code": 200
}
}
}
}
]
}
}
跳过无效集群
默认情况下,如果在请求中任何一个集群是无效的,那么跨集群搜索将返回一个错误。
设置集群的skip_unavailable
为true
,在跨集群搜索期间跳过一个无效的集群。
根据以下cluster update setting API
请求,设置cluster_two
集群skip_unavailable
为true
curl -X PUT "localhost:9200/_cluster/settings?pretty" -H 'Content-Type: application/json' -d'
{
"persistent": {
"cluster.remote.cluster_two.skip_unavailable": true
}
}
'
提示:如果在跨集群搜索期间 cluster_two 断开连接或不可用,Elasticsearch 将不会在最终结果中包含来自该集群的匹配文档。
嗅探模式下选择网关和种子节点
对于使用嗅探连接模式的远程集群,需要通过您的网络从本地集群访问网关和种子节点。
默认情况下任何非主节点的节点都可以充当网关节点。你可以通过设置cluster.remote.node.attr.gateway
为true
来定义一个节点为网关节点。
对于跨集群搜索,我们推荐你使用能够充当搜索请求协调节点的节点来担任网关节点。如果需要,集群中的种子节点可以是网关节点的子集。
跨集群搜索怎么处理网络延迟
因为跨集群搜索涉及返送请求到远程集群,任何网络延迟都可能影响搜索速度。为了避免低效率查询,跨集群搜索提供两个选项来处理网络延迟:
- 最小的网络往返:默认情况下,ElasticSearch会减少远程集群之前的网络往返次数。这样减少了网络延迟对查询速度的影响。然而,ElasticSearch不能减少在很大搜索的请求中减少网络往返次数,其中包含
scroll
和inner hits
。可以查看Minimize network roundtrips
来学习此选项的工作原理。 - 不最小网络往返:对于包含
scoll
和inner hits
的搜索查询,ElasticSearch向每个远程集群发送多个outgoing
和ingoing
请求。您还可以通过将ccs_minimize_roundtrips
参数设置为false
来选择此选项。虽然通常较慢,但这种方法可能适用于低延迟的网络。可以查看Don’t minimize network roundtrips
来学习此选项的工作原理。
Minimize network roundtrips
以下是当您最小化网络往返时跨集群搜索的工作原理。
-
您向本地集群发送跨集群搜索请求。该集群中的协调节点接收并解析请求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-fu1bzoib-1625541935067)(https://www.elastic.co/guide/en/elasticsearch/reference/current/images/ccs/ccs-min-roundtrip-cluster-search.svg)]
-
协调节点向每个集群发送单个搜索请求,包括本地集群。每个集群独立执行搜索请求,将其自己的集群级别设置应用于请求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-JDk6QUJV-1625541935070)(https://www.elastic.co/guide/en/elasticsearch/reference/current/images/ccs/ccs-min-roundtrip-cluster-search.svg)]
-
每个远程集群将其搜索结果发送回协调节点。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-uynowr9b-1625541935071)(https://www.elastic.co/guide/en/elasticsearch/reference/current/images/ccs/ccs-min-roundtrip-cluster-results.svg)]
-
从每个集群收集结果后,协调节点在跨集群搜索响应中返回最终结果。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-MAxCj1Iv-1625541935072)(https://www.elastic.co/guide/en/elasticsearch/reference/current/images/ccs/ccs-min-roundtrip-client-response.svg)]
Don’t minimize network roundtripsedit
以下是当您不最小化网络往返时跨集群搜索的工作原理。
-
您向本地集群发送跨集群搜索请求。该集群中的协调节点接收并解析请求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-qF45hjTJ-1625541935073)(https://www.elastic.co/guide/en/elasticsearch/reference/current/images/ccs/ccs-min-roundtrip-client-request.svg)]
-
协调节点向每个远程集群发送搜索分片 API 请求。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Uy7u2hn9-1625541935074)(https://www.elastic.co/guide/en/elasticsearch/reference/current/images/ccs/ccs-min-roundtrip-cluster-search.svg)]
-
每个远程集群将其响应发送回协调节点。此响应包含有关将在其上执行跨集群搜索请求的索引和分片的信息。
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-Jpi8tY2d-1625541935074)(https://www.elastic.co/guide/en/elasticsearch/reference/current/images/ccs/ccs-min-roundtrip-cluster-results.svg)]
-
协调节点向每个分片发送搜索请求,包括其自己集群中的分片。每个分片独立执行搜索请求。
-
每个分片将其搜索结果发送回协调节点。
-
从每个集群收集结果后,协调节点在跨集群搜索响应中返回最终结果。