默认情况下,搜索响应中的每个命中都包括document _source,这是在索引文档时提供的整个JSON对象。建议使用两种方法从搜索查询中检索选定字段:
-
使用 fields 选项提取索引映射中存在的字段的值
-
如果需要访问在索引时传递的原始数据,请使用_source选项
我们可以同时使用这两种方法,但首选fields选项,因为它同时参考文档数据和索引映射。在某些情况下,我们可能希望使用其他方法检索数据。
The fields option
要检索搜索响应中的特定字段,请使用fields参数。因为它参考索引映射,所以fields参数提供了几个优于直接引用_source的优点。具体而言,字段参数:
-
以与映射类型匹配的标准化方式返回每个值
-
接受多个字段和字段别名
-
格式化日期和空间数据类型
-
检索运行时字段值
-
返回脚本在索引时计算的字段
还考虑了其他映射选项,包括上面的ignore_above、ignore_malformed和null_value。
fields选项返回值的方式与Elasticsearch索引值的方式相匹配。对于标准字段,这意味着fields选项在_source中查找值,然后使用映射解析并格式化它们。
Search for specific fields
搜索特定的字段,以下搜索请求使用fields参数检索user.id字段、以http.response.开头的所有字段和@timestamp字段的值。
使用对象表示法,可以传递format参数以自定义返回日期或地理空间值的格式。
POST my-index-000001/_search
{
"query": {
"match": {
"user.id": "kimchy"
}
},
"fields": [
"user.id",
"http.response.*", (1)
{
"field": "@timestamp",
"format": "epoch_millis" (2)
}
],
"_source": false
}
(1)接受完整字段名和通配符模式。
(2)使用format参数为字段值应用自定义格式。
Response always returns an array
响应总是返回一个数组。
fields响应始终为每个字段返回一个值数组,即使_source中只有一个值。这是因为Elasticsearch没有专用的数组类型,任何字段都可能包含多个值。fields参数也不能保证数组值按特定顺序返回。
响应将值作为一个平面列表包含在每个命中的字段部分中。因为fields参数不获取整个对象,所以只返回页字段。
{
"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
]
}
}
]
}
}
检索nested字段
nested字段的字段响应与常规对象字段的字段响应略有不同。常规对象字段中的叶值以平面列表的形式返回,而嵌套字段中的值则分组以保持原始嵌套数组中每个对象的独立性。对于嵌套字段数组中的每个条目,值将再次以平面列表的形式返回,除非父嵌套对象中存在其他嵌套字段,在这种情况下,对更深的嵌套字段再次重复相同的过程。
给定以下映射,其中user是嵌套字段,在为以下文档编制索引并检索用户字段下的所有字段后:
PUT my-index-000001
{
"mappings": {
"properties": {
"group" : { "type" : "keyword" },
"user": {
"type": "nested",
"properties": {
"first" : { "type" : "keyword" },
"last" : { "type" : "keyword" }
}
}
}
}
}
PUT my-index-000001/_doc/1?refresh=true
{
"group" : "fans",
"user" : [
{
"first" : "John",
"last" : "Smith"
},
{
"first" : "Alice",
"last" : "White"
}
]
}
POST my-index-000001/_search
{
"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字段:
POST my-index-000001/_search
{
"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模式直接以嵌套用户字段为目标时,不会返回任何值,因为该模式与任何页字段都不匹配。
Retrieve unmapped fields
检索未映射的字段
默认情况下,“fields”参数仅返回映射字段的值。但是,Elasticsearch允许在_source中存储未映射的字段,例如将动态字段映射设置为false,或者使用enabled : false的对象字段。这些选项禁用对象内容的解析和索引。
要从_source检索对象中未映射的字段,请使用“fields”部分中的“include_unmapped”选项:
PUT my-index-000001
{
"mappings": {
"enabled": false (1)
}
}
PUT my-index-000001/_doc/1?refresh=true
{
"user_id": "kimchy",
"session_data": {
"object": {
"some_field": "some_value"
}
}
}
POST my-index-000001/_search
{
"fields": [
"user_id",
{
"field": "session_data.object.*",
"include_unmapped" : true (2)
}
],
"_source": false
}
(1)禁用所有映射。
(2)包括与此字段模式匹配的未映射字段。
响应将包含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"
]
}
}
]
}
}
The _source option
我们可以使用_source参数选择返回源的哪些字段。这称为源过滤。
以下搜索API请求将_source request body参数设置为false。响应中不包括文档源。
GET /_search
{
"_source": false,
"query": {
"match": {
"user.id": "kimchy"
}
}
}
若要仅返回源字段的子集,请在_source参数中指定通配符(*)模式。以下搜索API请求仅返回obj字段及其属性的源。
GET /_search
{
"_source": "obj.*",
"query": {
"match": {
"user.id": "kimchy"
}
}
}
我们还可以在_source字段中指定通配符模式数组。以下搜索API请求仅返回obj1和obj2字段及其属性的源。
GET /_search
{
"_source": [ "obj1.*", "obj2.*" ],
"query": {
"match": {
"user.id": "kimchy"
}
}
}
对于更精细的控制,可以在_source参数中指定包含 includes和 excludes模式数组的对象。
如果指定了includes属性,则只返回与其模式之一匹配的源字段。可以使用excludes属性从该子集中排除字段。
如果未指定includes属性,则返回整个文档源,不包括与excludes属性中的模式匹配的任何字段。
以下搜索API请求仅返回obj1和obj2字段及其属性的源,不包括任何子description字段。
GET /_search
{
"_source": {
"includes": [ "obj1.*", "obj2.*" ],
"excludes": [ "*.description" ]
},
"query": {
"term": {
"user.id": "kimchy"
}
}
}