网络知识 娱乐 es-从搜索中检索选定的字段

es-从搜索中检索选定的字段

从搜索中检索选定的字段

Retrieve selected fields from a search(文档学习)

https://www.elastic.co/guide/en/elasticsearch/reference/7.13/search-fields.html#source-filtering

默认情况下,搜索响应中的每个命中都包括document的 _source部分,这是在索引文档时提供的整个JSON对象。
在这里插入图片描述

建议使用两种方法从搜索查询中检索选定字段:
(1)使用 fields 选项提取索引映射中存在的字段的值
(2)如果需要访问在索引时传递的原始数据,请使用_source选项
我们可以同时使用这两种方法,但首选fields选项,因为它同时参考文档数据和索引映射。在某些情况下,我们可能希望使用其他方法检索数据。
其他的话还有三种,补充使用
(3)docvalue_fields
使用 docvalue_fields 参数获取选定字段的值。当返回一个数量比较少的doc value(例如keyword和date),这可能是一个不错的选择。
(4)stored_fields
使用 stored_fields 参数获取特定存储字段(使用store映射选项的字段)的值。
(5)script_fields
使用 script_fields 参数来检索每个命中的脚本评估,提取/输出新字段。

The fields option

要检索搜索响应中的特定字段,请使用fields参数。因为它参考索引映射,所以fields参数提供了几个优于直接引用_source的优点。具体而言,字段参数:

  • 以与映射类型匹配的标准化方式返回每个值
  • 接受multi-fileds和field aliases
  • 格式化date和spatial(空间)数据类型
  • 检索runtime field values
  • 返回脚本在索引时计算的字段

还考虑了其他映射选项,包括上面的ignore_above、ignore_malformed和null_value。

  • ignore_above
    字符串元素的长度超过ignore_above不会被索引或存储

  • ignore_malformed
    允许的映射类型中忽略格式错误的内容

  • null_value

    fields选项返回值的方式与Elasticsearch索引值的方式相匹配。对于标准字段,这意味着fields选项在_source中查找值,然后使用映射解析并格式化它们。

(1)Search for specific fields

搜索指定的字段。比如text,keyword,objec,nested,date,spatial等字段都可以。
使用对象表示法,可以传递format参数以自定义返回日期或地理空间值的格式。

  • date and date_nanos 字段 使用date from
  • Spatial fields 使用 GeoJSON/wkt

以下搜索请求使用fields参数检索user.id字段、以http.response.开头的所有字段和@timestamp字段的值。

数据源

##数据源
DELETE my-index-000001

##spatial 要定类型,必须先创建mapping
PUT my-index-000001
{
  "mappings": {
    "properties": {
      "location.one": {"type": "geo_point"},
      "location.two": {"type": "geo_point"},        
      "location.three": {"type": "geo_point"},        
      "location.four": {"type": "geo_point"},        
      "location.five": {"type": "geo_point"},
      "username": {
        "type": "nested",
        "properties": {
          "first" : { "type" : "keyword" },
          "last" : { "type" : "keyword" }
        }
      },
      "timestamp":{
           "type": "date",
           "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis",
           "ignore_malformed": false,
           "null_value": null
      }
    }
  }
}

PUT my-index-000001/_doc/1
{
  "user": {
    "id": "kimchy",
    "name": "kimchy wang",
    "age": 12
  },
  "http": {
    "response": {
      "status_code": 200,
      "bytes": "1070000"
    }
  },
  "@timestamp": "2018-10-18T12:20:51.603Z",
  "timestamp": 1539865251603,
  "ip_addr": "192.168.1.1",
  "location": {
    "one": {"lat": 41.12,"lon": -71.34},
    "two": "41.12,-71.34",
    "three": "drm3btev3e86",
    "four": [41.12, -71.34],
    "five" : "POINT (41.12 -71.34)"
  },
  "username":{
    "first": "John",
    "last": "Smith"
  }
}

##查看mapping结构
GET /my-index-000001/_mapping

fields指定字段 请求

##1.object字段
##2.前缀模糊匹配
##3.date 用户epoch_millis输出
##4.Spatial 用wkt输出
##"_source": false 不返回_source
POST my-index-000001/_search
{
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  },
  "fields": [
    "user.id",
    "http.response.*",         
    {
      "field": "@timestamp",
      "format": "epoch_millis" 
    },
    {
      "field": "location.*",
      "format": "geojson"
    },
     {
      "field": "location.*",
      "format": "wkt"
    }
  ],
  "_source": false
}

fields指定字段返回 响应结果

##1.object字段
##2.前缀模糊匹配
##3.date 用户epoch_millis输出
##4.Spatial 用wkt输出
##"_source": false 不返回_source
{
  "took" : 2,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "my-index-000001",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.2876821,
        "fields" : {
          "@timestamp" : [
            "1539865251603"
          ],
          "location.three" : [
            "POINT (-71.34000029414892 41.119999922811985)"
          ],
          "user.id" : [
            "kimchy"
          ],
          "http.response.bytes.keyword" : [
            "1070000"
          ],
          "http.response.bytes" : [
            "1070000"
          ],
          "location.two" : [
            "POINT (-71.34 41.12)"
          ],
          "location.one" : [
            "POINT (-71.34 41.12)"
          ],
          "location.five" : [
            "POINT (41.12 -71.34)"
          ],
          "http.response.status_code" : [
            200
          ],
          "location.four" : [
            "POINT (41.12 -71.34)"
          ]
        }
      }
    ]
  }
}

(2)Response always returns an array

  • 响应总是返回一个数组。
  • fields响应始终为每个字段返回一个值数组,即使_source中只有一个值。这是因为Elasticsearch没有专用的数组类型,任何字段都可能包含多个值。fields参数也不能保证数组值按特定顺序返回。
  • 响应将值作为一个平面列表包含在每个命中的字段部分中。因为fields参数不获取整个对象,所以只返回leaf字段。
  • 这里对比nested的结果看,就知道平铺列表形式了。
    在这里插入图片描述

(3)fields response for nested 检索nested字段

  • nested字段的字段响应与常规对象字段的字段响应略有不同。常规对象字段中的叶值以平面列表的形式返回,而嵌套字段中的值则分组以保持原始嵌套数组中每个对象的独立性。对于嵌套字段数组中的每个条目,值将再次以平面列表的形式返回,除非父嵌套对象中存在其他嵌套字段,在这种情况下,对更深的嵌套字段再次重复相同的过程。
  • 给定以下映射,其中user是嵌套字段,检索用户字段下的所有字段:

数据源

DELETE my-index-000002

PUT my-index-000002
{
  "mappings": {
    "properties": {
      "group" : { "type" : "keyword" },
      "user": {
        "type": "nested",
        "properties": {
          "first" : { "type" : "keyword" },
          "last" : { "type" : "keyword" }
        }
      },
      "addr":{
        "properties": {
          "country": { "type" : "keyword" },
          "province": { "type" : "keyword" },
          "city": { "type" : "keyword" },
          "description": { "type" : "keyword" } 
        }
      }
    }
  }
}
##user-nested tel-object(非定义) add-object(定义) 
PUT my-index-000002/_doc/1?refresh=true
{
  "group": "fans",
  "user": [
    {
      "first": "John",
      "last": "Smith"
    },
    {
      "first": "Alice",
      "last": "White"
    }
  ],
  "tel": {
    "number": "13334567890",
    "area_code": "86"
  },
  "addr": {
    "country": "CN",
    "province": "YN",
    "city": "KM",
    "description": "地址信息"
  }
}

GET /my-index-000002/_mapping

fields指定nested 请求

  • 1.tel-object(非定义) 区分了text,keyword
  • 2.add-object(定义) keyword
  • 3.user-nested
POST my-index-000002/_search
{
  "fields": ["*"],
  "_source": false
}

## 或者
POST my-index-000002/_search
{
  "fields": ["user.first","user.last"],
  "_source": false
}

fields指定nested 响应结果

##响应
##1.tel-object(非定义) 区分了text,keyword
##"tel.number"
##"tel.number.keyword"
##"tel.area_code" 
##"tel.area_code.keyword"
##2.add-object(定义) keyword
##"addr.country"
##"addr.description"
##"addr.province"
##"addr.city"
##3.user-nested (一层一层的以数组形式组织,而不是平铺的设计)
##"user" : ["last" : ["Smith" ],"first" : [ "John"] },{"last" : ["White"],"first" : ["Alice"]}]

{
  "took" : 1,
  "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-000002",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "fields" : {
          "tel.number" : [
            "13334567890"
          ],
          "tel.area_code.keyword" : [
            "86"
          ],
          "tel.number.keyword" : [
            "13334567890"
          ],
          "addr.country" : [
            "CN"
          ],
          "tel.area_code" : [
            "86"
          ],
          "addr.description" : [
            "地址信息"
          ],
          "addr.province" : [
            "YN"
          ],
          "addr.city" : [
            "KM"
          ],
          "user" : [
            {
              "last" : [
                "Smith"
              ],
              "first" : [
                "John"
              ]
            },
            {
              "last" : [
                "White"
              ],
              "first" : [
                "Alice"
              ]
            }
          ],
          "group" : [
            "fans"
          ]
        }
      }
    ]
  }
}

(4)Retrieve unmapped fields 检索未映射的字段

  • 默认情况下,“fields”参数仅返回映射字段的值。但是,Elasticsearch允许在_source中存储未映射的字段,例如将动态字段映射设置为false,或者使用enabled : false的对象字段。这些选项禁用对象内容的解析和索引。
  • 要从_source检索对象中未映射的字段,请使用“fields”部分中的“include_unmapped”选项:

enabled : false 禁用所有映射

DELETE my-index-000003

##禁用所有映射
PUT my-index-000003
{
  "mappings": {
    "enabled": false 
  }
}

##index
PUT my-index-000003/_doc/1?refresh=true
{
  "user": {
    "id": "kimchy"
  },
  "session_data": {
    "object": {
      "some_field": "some_value"
    }
  }
}

include_unmapped设置返回为映射的字段 请求

include_unmapped设置返回为映射的字段,也包括与此字段模式匹配的未映射字段。

##设置session_data.object.* 的include_unmapped属性为true可查询到为未映射的session_data.object.* 前缀开头的字段。
POST my-index-000003/_search
{
  "fields": [
    "user.id",
    {
      "field": "session_data.object.*",
      "include_unmapped" : true 
    }
  ],
  "_source": false
}

POST my-index-000003/_search
{
  "fields": [
    "user.id",
    {
      "field": "session_data.object.*",
      "include_unmapped" : true 
    }
  ],
  "_source": false
}

include_unmapped 响应结果

  • 响应将包含session_data.object.*路径下的字段结果,即使字段未映射。user_id字段也未映射,但它不会包含在响应中,因为对于该字段模式,include_unmapped未设置为true。
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 1.0,
    "hits" : [
      {
        "_index" : "my-index-000003",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 1.0,
        "fields" : {
          "session_data.object.some_field" : [
            "some_value"
          ]
        }
      }
    ]
  }
}


The _source option

  • 我们可以使用_source参数选择返回源的哪些字段。这称为源过滤。
    以下搜索API请求将_source request body参数设置为false。响应中不包括文档源。

1.响应中不包括文档源_source

数据源


DELETE my-index-000004
PUT my-index-000004/_doc/1?refresh=true
{
  "group": "fans",
  "user": {
    "id": "kimchy",
    "age": 12,
    "description": "用户信息"
  },
  "tel": {
    "number": "13334567890",
    "area_code": "86",
     "description": "手机信息"
  },
  "addr": {
    "country": "CN",
    "province": "YN",
    "city": "KM",
    "description": "地址信息"
  }
}

返回_source部分 设置 “_source”: true

GET /my-index-000004/_search
{
  "_source": true,
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

返回_source部分 响应结果

  "hits" : [
      {
        "_index" : "my-index-000004",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.2876821,
        "_source" : {
          "group" : "fans",
          "user" : {
            "id" : "kimchy",
            "age" : 12,
            "description" : "用户信息"
          },
          "tel" : {
            "number" : "13334567890",
            "area_code" : "86",
            "description" : "手机信息"
          },
          "addr" : {
            "country" : "CN",
            "province" : "YN",
            "city" : "KM",
            "description" : "地址信息"
          }
        }
      }
    ]

不返回_source部分 设置 “_source”: false

GET /my-index-000004/_search
{
  "_source": false,
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

不返回_source部分 响应结果

"hits" : [
      {
        "_index" : "my-index-000004",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.2876821
      }
    ]

2.返回指定的字段 “_source”: [“tel.*”]

返回指定的单字段 请求

若要仅返回源字段的子集,请在_source参数中指定通配符(*)模式。以下搜索API请求仅返回tel字段及其属性的源。

GET /my-index-000004/_search
{
  "_source": ["tel.*"],
  "query": {
    "match": {
      "user.id": "kimchy"
    }
  }
}

返回指定的单字段 响应结果

  • 返回"tel.*"字段
{
  "took" : 0,
  "timed_out" : false,
  "_shards" : {
    "total" : 1,
    "successful" : 1,
    "skipped" : 0,
    "failed" : 0
  },
  "hits" : {
    "total" : {
      "value" : 1,
      "relation" : "eq"
    },
    "max_score" : 0.2876821,
    "hits" : [
      {
        "_index" : "my-index-000004",
        "_type" : "_doc",
        "_id" : "1",
        "_score" : 0.2876821