从搜索中检索选定的字段

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-000002PUT 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,"_source" : {"tel" : {"number" : "13334567890","area_code" : "86","description" : "手机信息"}}}]}
}

3.返回指定的多个字段 “_source”: [“tel.","user.”]

我们还可以在_source字段中指定通配符模式数组。以下搜索API请求仅返回tel和user字段及其属性的源。

_source返回指定的多个字段 请求

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

_source返回指定的多个字段 响应结果

{"took" : 1,"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,"_source" : {"tel" : {"number" : "13334567890","area_code" : "86","description" : "手机信息"},"user" : {"description" : "用户信息","id" : "kimchy","age" : 12}}}]}
}

4.返回指定的字段+不返回指定字段 includes+excludes

  • 对于更精细的控制,可以在_source参数中指定包含 includes和 excludes模式数组的对象。
  • 如果指定了includes属性,则只返回与其模式之一匹配的源字段。可以使用excludes属性从该子集中排除字段。
    ##如果未指定includes属性,则返回整个文档源,不包括与excludes属性中的模式匹配的任何字段。

includes+excludes 请求

以下搜索API请求仅返回 tel和user 字段及其属性的源,不包括任何子description字段。

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

includes+excludes 响应结果

{"took" : 1,"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,"_source" : {"tel" : {"number" : "13334567890","area_code" : "86"},"user" : {"id" : "kimchy","age" : 12}}}]}
}

Other methods of retrieving data

使用fields 选项通常是更好的选择,除非您绝对需要强制加载存储的或 docvalue_fields。
文档的_source 在 Lucene 中存储为单个字段。这种结构意味着必须加载和解析整个 _source对象,即使您只请求它的一部分。

  • 为避免此限制,您可以尝试加载字段的其他选项:
  • (1)docvalue_fields
  • 使用 docvalue_fields 参数获取选定字段的值。当返回一个数量比较少的doc value(例如keyword和date),这可能是一个不错的选择。
  • (2)stored_fields
  • 使用 stored_fields 参数获取特定存储字段(使用store映射选项的字段)的值。
  • Elasticsearch 总是尝试从 _source 加载值。这种行为与源过滤具有相同的含义,其中 Elasticsearch 需要加载和解析整个_source 以仅检索一个字段。

docvalue_fields

使用 docvalue_fields 参数返回搜索响应中一个或多个字段的文档值(doc value)。

字段检索:_source 和 doc values:

  • _source :存储 post 提交到ES的原始 json 内容
    (1)source是一个大字段,包含索引期的文档json. 会占用很多存储空间。数据压缩存储,读source中的部分字段时,需要把整个source中的json读取出来,读取会有额外解压开销。
    (2)默认会存储所有字段,可以excludes排除的字段,这可以减少存到source中的数据大小,从而减少磁盘空间占用.但是在查询时,将无法得到被排除字段的原始值.
    (3)不需要读取原始字段内容可以考虑关闭,但关闭后无法 reindex
    (4)如果禁用es的source(即文档不存储到source),在没有source的情况下,旧文档的某个字段值可以通过doc values或stored fields来获得.
  • doc values
    (1)为了支持排序、聚合。
    (2)会占用额外存储空间,与 source 独立,同时开启 doc_values 和 _source 则会将该字段原始内容保存两份。
    (3)doc_value 与 _source 是存储相同的值。doc_values 数据在磁盘上采用列式存储,关闭后无法使用排序和聚合。
    (4)doc_value由于每个字段是分开存储的,Elasticsearch 只读取请求的字段值,可以避免加载整个文档_source。
    (5)默认支持fields支持存储doc values。但,text 或 text_annotated 字段是不支持doc values(文档值)。

存储:store fields vs doc values

在lucene中将一个文档编入索引时,字段的原始值会丢失. 字段被分析(analyze),转换(transform)以至编入索引. 在没有其他额外添加的数据结构的情况下,当我们检索文档时,我们只能得到被检索文档的id,而没有文档的原始字段. 为了去获得这些信息,我们需要额外的数据结构. lucene提供了两种可能性来实现这个,stored fields 和 doc values.

  • store fields
    stored fields用于存储没有经过任何分析(without any analysis)的字段值,以实现在查询时能得到这些原始值.
    stored fields在磁盘上以行的方式放置: 每个文档对应一个行,这个行包含该文档所有的stored fields.

  • doc values
    doc values用于加速一些诸如聚合(aggregation),排序(sorting),分组(grouping)的操作. doc values 也可以被用来在查询时返回字段值. 例外是doc values不能用来存储text类型的字段.
    doc values 以列的方式存储. 不同文档的相同字段被连续地存储在一起。 这种存储方式,可以直接访问一个特定的文档的特定字段. 更有效率。doc_value由于每个字段是分开存储的,Elasticsearch 只读取请求的字段值,可以避免加载整个文档_source。

排序:Doc Values vs Field Data

ES排序是针对字段原始内容进⾏的。 倒排索引⽆法发挥作⽤
需要⽤到正排索引。通过⽂档 Id 和字段快速得到字段原始内容
Elasticsearch 有两种实现⽅法
1.Fielddata (打开fielddata,可对 text 字段进行排序)
2.Doc Values (列式存储,对 Text 类型⽆效)

vs Doc Values Field data
创建时间 索引时,和倒排索引⼀起创建 搜索时候动态创建
创建位置 磁盘⽂件 JVM Heap
优点 避免⼤量内存占⽤ 索引速度快,不占⽤额外的磁盘空间
缺点 降低索引速度,占⽤额外磁盘空间 ⽂档过多时,动态创建开销⼤,占⽤过多JVM Heap
缺省值 ES 2.x 之后 ES 1.x 及之前

1. docvalue_fields + text类型 不存储doc values。报错。

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

  • user.id 字段:text类型
  • http.response. 开头的字段:部分是text类型
  • @timestamp 字段:date类型

docvalue_fields + text类型 请求

GET my-index-000001/_search
{"query": {"match": {"user.id": "kimchy"}},"docvalue_fields": ["user.id","http.response.*",{"field": "date","format": "epoch_millis"},{"field": "location.*","format": "wkt"}]
}

响应结果 docvalue_fields 不支持text类型 报错

"Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [user.id] in order to load field data by uninverting the inverted index. Note that this can use significant memory.

2. docvalue_fields + 非text类型

项目 Value
user.id 字段 text类型
http.response.* 部分text类型
@timestamp字段 date类型
http.response.status_code: long
user.age字段 long
date字段 date类型
location.* 不支持geo_point… Field [location.three] of type [geo_point] does not support custom formats
username nested,不能使用 docvalue_fields 参数来检索嵌套对象的文档值。如果您指定一个嵌套对象,则搜索会为该字段返回一个空数组 ([ ])。要访问嵌套字段,请使用 inner_hits 参数的 docvalue_fields 属性。

docvalue_fields + 非text类型 请求

GET my-index-000001/_search
{"_source": "false","query": {"match": {"user.id": "kimchy"}},"docvalue_fields": ["@timestamp","http.response.status_code", "user.age", {"field": "date","format": "epoch_millis" },"username"]
}

docvalue_fields + 非text类型 响应结果

  • “username” 非text类型 nested 返回为空
{"took" : 1,"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,"_source" : { },"fields" : {"user.age" : [12],"@timestamp" : ["2018-10-18T12:20:51.603Z"],"http.response.status_code" : [200]}}]}
}

3. docvalue_fields + nested类型

  • nested 使用inner_hits解决docvalue_fields查询为空数组的问题
  • docvalue_fields + nested 查询 + inner_hits 查询到docvalue_fields

docvalue_fields + nested + inner_hits 请求

  • usernam为nested类型,使用docvalue_fields 返回为空,可以利用inner_hits得到nested类型的字段。
GET my-index-000001/_search
{"_source": "false","query": {"nested": {"path": "username","query": {"match_all": {}},"inner_hits": {"docvalue_fields": ["username.id","username.name"]}}}
}

docvalue_fields + nested + inner_hits 响应结果

{"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-000001","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : { },"inner_hits" : {"username" : {"hits" : {"total" : {"value" : 1,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "my-index-000001","_type" : "_doc","_id" : "1","_nested" : {"field" : "username","offset" : 0},"_score" : 1.0,"_source" : {"last" : "Smith","first" : "John"}}]}}}}]}
}

stored_fields 存储字段

  • 可以使用store映射选项来存储单个字段的值。您可以使用 stored_fields 参数将这些存储的值包含在搜索响应中。
  • stored_fields 参数用于在映射中显式标记为存储的字段,默认情况下处于关闭状态,通常不推荐使用。改为使用 source filtering 来选择要返回的原始源文档的子集。
  • 允许为搜索命中表示的每个文档选择性地加载特定的存储字段。

1.stored_fields 查询存储字段

mapping 设置 store

  • store不指定,默认为false。
  • “store”: false ,field只存储在"_source" field中。减少字段存储可以减少开销
  • “store”: true ,field的value会存储在一个跟 _source 平级的独立的field中。同时也会存储在_source中,所以有两份拷贝。
##nested 中不要加分词,并且不要使用type=text的类型
DELETE my-index-store
PUT my-index-store
{"mappings": {"properties": {"title": {"type": "text","store": true},"date": {"type": "date","store": true},"content": {"type": "text"},"likes": {"type": "long","store": false},"fans": {"type": "nested","properties": {"id": {"type": "keyword","store": true,"ignore_above": 256},"name": {"type": "text"}}}}}
}PUT my-index-store/_doc/1
{"title":   "Some short title","date":    "2015-01-01","content": "A very long content field...","likes": 345,"fans":[{"id":"123","name":"木头人"},{"id":"321","name":"上链接"}]
}GET my-index-store/_mapping

stored_fields 请求

  • “title”, “date”:store 为 true,能被查询到
  • “content”:store 默认 false,不能被查询到
  • “likes”:store 指定为 false,不能被查询到
GET my-index-store/_search
{"stored_fields": [ "title", "date", "content", "likes" ]
}

stored_fields 响应结果

## "title", "date":store 为 true,能被查询到
## "content":store 默认 false,不能被查询到
## "likes":store 指定为 false,不能被查询到
{"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-store","_type" : "_doc","_id" : "1","_score" : 1.0,"fields" : {"date" : ["2015-01-01T00:00:00.000Z"],"title" : ["Some short title"]}}]}
}

2. stored_fields查空数组[]

  • stored_fields查空数组[],只返回_id and _type

“stored_fields”: [] 请求

GET my-index-store/_search
{"stored_fields": []
}

“stored_fields”: [] 响应结果

{"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-store","_type" : "_doc","_id" : "1","_score" : 1.0}]}
}

3. stored_fields + 特殊字段(leaf fields,nested类型字段)

  • 如果请求的字段未存储(store映射设置为 false),它们将被忽略。比如content/likes字段,被设置为store=false。
  • 像 _routing 这样的元数据字段永远不会作为数组返回。
  • leaf fields (叶字段)也只能通过 stored_fields 选项返回。如果指定了object字段,它将被忽略。
  • stored_fields 不能用于加载嵌套对象中的字段——如果字段在其路径中包含嵌套对象,则不会为该存储字段返回任何数据。要访问嵌套字段,stored_fields 必须在 inner_hits 块中使用。

stored_fields + nested类型字段的问题 请求

GET my-index-store/_search
{"stored_fields": [ "fans.id", "fans.name"]
}

stored_fields + nested类型字段的问题 响应结果

  • 嵌套对象,则不会返回任何数据
{"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-store","_type" : "_doc","_id" : "1","_score" : 1.0}]}
}

stored_fields + nested + inner_hits 查询stroe字段 请求

GET my-index-store/_search
{"_source": "false","query": {"nested": {"path": "fans","query": {"match_all": {}},"inner_hits": {"_source": "false","stored_fields": ["fans.id","fans.name"]}}}
}

stored_fields + nested + inner_hits 查询stroe字段 响应结果

  • fans nested类型部分返回了数据
{"took" : 9,"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-store","_type" : "_doc","_id" : "1","_score" : 1.0,"_source" : { },"inner_hits" : {"fans" : {"hits" : {"total" : {"value" : 2,"relation" : "eq"},"max_score" : 1.0,"hits" : [{"_index" : "my-index-store","_type" : "_doc","_id" : "1","_nested" : {"field" : "fans","offset" : 0},"_score" : 1.0,"_source" : { },"fields" : {"fans.id" : ["123"]}},{"_index" : "my-index-store","_type" : "_doc","_id" : "1","_nested" : {"field" : "fans","offset" : 1},"_score" : 1.0,"_source" : { },"fields" : {"fans.id" : ["321"]}}]}}}}]}
}

4. Disable stored fields 禁用存储字段 “stored_fields”: “none

  • 要完全禁用存储字段(和元数据字段),请使用:none

“stored_fields”: “none” 请求

GET my-index-store/_search
{"stored_fields": "_none_"
}

“stored_fields”: “none” 响应结果

  • 查询不到_source
{"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-store","_type" : "_doc","_score" : 1.0}]}
}

script_fields

  • 可以使用 script_fields 参数来检索每个命中的脚本评估(基于不同的字段)。

1.script_fields 使用脚本查询指定字段

script_fields+doc[‘***’].value 请求

##doc['user.age'].value 提取age的信息作为新字段输出
##"@timestamp": "2018-10-18T12:20:51.603Z", 提取year 作为新字段输出
GET my-index-000001/_search
{"query": {"match_all": {}},"script_fields": {"test1": {"script": {"lang": "painless","source": "doc['age'].value * 2"}},"test3": {"script": {"lang": "painless","source": "doc['@timestamp'].value.year"}}}
}

script_fields+doc[‘***’].value 响应结果

  • doc[‘user.age’].value 提取age的信息作为新字段输出
  • “@timestamp”: “2018-10-18T12:20:51.603Z”, 提取year 作为新字段输出
{"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-000001","_type" : "_doc","_id" : "1","_score" : 1.0,"fields" : {"test3" : [2018],"test1" : [24]}}]}
}

script_fields+params[‘_source’][‘***’].value 请求

  • 脚本字段还可以访问_source 文档并使用 params[‘_source’] 提取要从中返回的特定元素。
GET my-index-000001/_search
{"query": {"match_all": {}},"script_fields": {"test1": {"script": "params['_source']['user']"}}
}

script_fields+params[‘_source’][‘***’].value 响应结果

  • fields返回user部分字段。
{"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-000001","_type" : "_doc","_id" : "1","_score" : 1.0,"fields" : {"test1" : [{"name" : "kimchy wang","id" : "kimchy","age" : 12}]}}]}
}

2. doc[‘my_field’].value vs params[‘_source’][‘my_field’]

  • 1.使用doc,doc是加载到内存中,直接从内存中获取对象的,会消耗更多的内存,查询也更快。doc另外一个显著特点就是只能访问简单字段值,doc[…] 表示法仅允许简单的值字段(您不能从中返回 json 对象)并且仅对未分析或基于单个术语的字段有意义。

  • 2.params是从磁盘中获取的,每次都要从磁盘取一次,所以速度相对较慢。所以一般情况下,我们更加推荐使用doc。

3. 简单字段值

根据官方的描述:Doc-values can only return “simple” field values like numbers, dates, geo- points, terms, etc, or arrays of these values if the field is multi-valued. It cannot return JSON objects.
即数字、日期、地理点、术语等或者这些值的数组,所以doc不支持json对象

小结(5种检索选定的字段方法)

(1)fields
使用fields 选项提取索引映射中存在的字段的值
(2)_source
使用_source选项访问在索引时传递的原始数据
(3)docvalue_fields
使用 docvalue_fields 参数获取选定字段的值。doc value类型主要是keyword和date,不支持text类型
(4)stored_fields
使用 stored_fields 参数获取特定存储字段(使用store映射选项的字段)的值。stored是要消耗内存的,有性能瓶颈
(5)script_fields
使用 script_fields 参数来检索每个命中的脚本评估,提取/输出新字段。doc[‘my_field’].value 是基于内存查询字段,params[‘_source’][‘my_field’] 是基于磁盘查询字段

es-从搜索中检索选定的字段相关推荐

  1. 关于电商搜索中Elasticsearch的正确使用姿势--检索篇

    文章目录 前言 检索的前一步 检索 分数 sort operator 二次召回 改变权重 组合查询 归因问题(functionScore) 聚合 结语 前言 书接上文,我们为电商项目做了个性化的索引配 ...

  2. ES修改mapping中的字段名称

    前言 我们都知道,在ES中一旦声明了字段名称,就不能对字段名称进行修改了.只能新增字段,不能删除.修改已经声明的mapping字段. 那么,如果我们需要修改mapping中的字段名称,需要怎么操作呢? ...

  3. 快速取出ES索引中该索引所有字段名称

    # 快速取出ES索引中该索引所有字段名称 # 1.通过命令 GET 索引名称/_mapping 获取该索引所有字段信息 # 2.取出"properties"中所有字段,如test_ ...

  4. #研发解决方案介绍#基于ES的搜索+筛选+排序解决方案

    郑昀 基于胡耀华和王超的设计文档 最后更新于2014/12/3 关键词:ElasticSearch.Lucene.solr.搜索.facet.高可用.可伸缩.mongodb.SearchHub.商品中 ...

  5. 极兔一面:10亿级ES海量搜索狂飙10倍,该怎么办?

    背景说明: ES高性能全文索引,如果不会用,或者没有用过,在面试中,会非常吃亏. 所以ES的实操和底层原理,大家要好好准备. 另外,ES调优是一个非常.非常核心的面试知识点,大家要非常重视. 在40岁 ...

  6. 关于电商搜索中Elasticsearch的正确使用姿势--配置篇

    文章目录 前言 什么是Elasticsearch ES快在哪里 创建索引 索引的基本配置 分片 分析器 Field分析器应用 copy_to multi-fields 结语 更新 前言 过年放假啦,总 ...

  7. Query理解在美团搜索中的应用

    分享嘉宾:刘亮 美团 资深算法工程师 编辑整理:吴雪松 出品社区:DataFunTalk 导读:在过去的20年中,搜索过程中处理查询的方式以及向用户显示结果的方式已完全改变.该过程已经从仅基于文本匹配 ...

  8. 美团搜索中NER技术的探索与实践

    1. 背景 命名实体识别(Named Entity Recognition,简称NER),又称作"专名识别",是指识别文本中具有特定意义的实体,主要包括人名.地名.机构名.专有名词 ...

  9. 有赞基于ES的搜索系统架构是如何演进的?

    本文从架构上介绍了有赞搜索系统演进产生的背景以及希望解决的问题. 有赞搜索平台是一个面向公司内部各项搜索应用以及部分 NoSQL 存储应用的 PaaS 产品,帮助应用合理高效的检索和多维过滤功能.有赞 ...

  10. 美团搜索中查询改写技术的探索与实践

    猜你喜欢 0.[免费下载]2022年1月热门报告盘点1.腾讯QQ信息流推荐业务实践2.小红书推荐中台实践3.微信视频号的实时推荐技术架构分享4.预训练模型在华为信息流推荐系统中的探索和应用5.腾讯PC ...

最新文章

  1. 基本电路元件和特性(2)电容器和电容vs.电感器和电感
  2. 练习一:GitHub Desktop下载及使用
  3. 温州大学《机器学习》课程课件(八、集成学习)
  4. svn服务器搭建-SuSE Linux Enterprise Server 11 SP3
  5. linux 线程 拷贝,linux下实现多线程拷贝命令
  6. asp.net 页面静态化
  7. aopaspect区别_spring 中的aop:advisor和aop:aspect有什么区别?
  8. 使用auditctl追踪文件变化
  9. oracle 12.1.0.2中对象锁对系统的较大影响
  10. 如何自学成为设计师_不会自学,你永远只能是个三流设计师
  11. 多页TIF转PDF 【JAVA】
  12. html常见基础标签大汇总
  13. #4036. 企鹅的游戏(penguin)
  14. 仙之侠道2玖章青门任务怎么做_仙之侠道Ⅱ攻略_仙之侠道Ⅱ柒章 任务全攻略 新手必看_牛游戏网魔兽地图专区...
  15. Spark Structured Steaming实战
  16. 团队建设:如何打造一个优秀的团队
  17. Vitalik:协议设计中的“封装复杂性” vs. “系统复杂性”
  18. TCP/IP详解卷1:第十四章 DNS 域名系统
  19. oracle归档日志 delete obsolete 保留一次全备,Rman Crosscheck删除失效归档
  20. board (双联通分量)

热门文章

  1. python小学口算题库生成器_PrimarySchoolMathematics
  2. 免费可商用图片网站合集
  3. OTA 差分升级包的制作
  4. 倒计时21天,房贷利率新政要来了,有银行已率先公布报价
  5. EMPLOYEE表的创建与查询
  6. 微信公众号开发引导用户关注公众号
  7. 更深一步了解,电容是起什么作用的?
  8. 这次跟大家聊聊技术,也聊聊人生
  9. 服务器没有信号给到继电器,dx-8型信号继电器为什么有自锁结构
  10. access to同义替换_access to 用法