所有字段是默认被 indexed arrow-up-right (被索引的),这使得它们是可搜索的.可以在脚本中排序,聚合和获取字段值,但是需要不同的搜索模式.
搜索需要回答一个问题 “哪个 document(文档) 包含这个 term (词条)”,然而排序和聚合需要回答一个不同的问题 " 这个字段在这个 document (文档)中的值是多少?".
许多字段可以使用index-time ,在磁盘上的doc_values 支持这种数据访问模式, 但是text 字段不支持doc_values 。
相反,text 字段使用查询时存在于内存的数据结构 fielddata .这个数据结构是第一次将字段用于聚合,排序,或者脚本时基于需求构建的。它是通过读取磁盘上的每个 segment (片段)的整个反向索引来构建的,将 term (词条)和 document (文档)关系反转,并将结果存储在内存中,在JVM 的堆中.
text 字段默认关闭 Fielddata
Fielddata 会消耗很多堆空间,尤其是加载高基数的 text 字段的时候.一旦fielddata 加载到堆中,它在 segment (片段)中的生命周期还是存在的.此外,加载 fielddata 是一件非常昂贵的过程,会导致用户体验到延迟的感觉.这就是为什么fielddata 默认关闭.
如果你尝试对文本字段上的脚本进行排序,访问值,你会看到此异常:
Field data 在text 字段上默认是关闭的.在[your_field_name] 上设置fielddata = true ,以便通过反转反向索引来加载内存中的fielddata 。 请注意,这可能会使用显着的内存。
在你开启fielddata 之前,考虑一下为什么你要在脚本中使用 text 来聚合,排序.通常这么做是没有意义的.
在索引之前分析text 字段,以至于像New York 这样的值可以通过new 或者 york 来搜索.当你可能想要一个称作 New York 的单一bucket(桶),term (词条)在这个字段上聚合会返回一个newbucket 和一个yorkbucket (桶).
相反,你应该使用text 字段进行全文搜索,以及一个开启doc_values 的unanalyzed (未分析)keyword arrow-up-right 字段用于聚合,如下:
Copy curl -XPUT 'localhost:9200/my_index?pretty' -H 'Content-Type: application/json' -d'
{
"mappings": {
"my_type": {
"properties": {
"my_field": { # 1
"type": "text",
"fields": {
"keyword": { # 2
"type": "keyword"
}
}
}
}
}
}
}
' 使用my_field.keyword 用于聚合,排序,或者脚本.
开启text 字段的fielddata
你可以使用以下的PUT mapping APIarrow-up-right 给一个已经存在的text 字段开启fielddata .
你为my_field 指定的映射应包含该字段已有的映射,再加上fielddata 参数.
建议:fielddata.* 参数必须在相同索引的相同名称的字段有相同的设置.可以使用 PUT mapping APIarrow-up-right 在现有字段上更新其值.
Global ordinals
Global ordinals (全局序数)是一个基于field data 和doc_values 的数据结构,它以字典顺序每户每个唯一term (词根)的增量编号.每个term (词根)都有一个唯一的数,term (词根)A是低于term (词根)B的.Global ordinals (全局序数)仅在textarrow-up-right 和keywordarrow-up-right 字段中支持.
Fielddata 和doc_values 也有 ordinals(序数),它是特定segment (段)和字段中所有term (词根)的唯一编号.Global ordinals (全局序数)只是建立在fielddata 和doc_values 之上,通过在segement ordinals 和global ordinals 之间提供映射,后者在整个shard (分片)中是唯一的.
Global ordinals 是用于使用segement ordinals (片段序数)的功能,例如排序和terms (词根)聚合,以提高执行时间.term (词根)聚合完全依赖于Global ordinals (全局序数)来执行shard (分片)级别的聚合,然后将global ordinals (全局序数)转换为真正的term (词根),term (词根)仅用于最终减少阶段,其结合不同shard (分片)的结果.
指定字段的Global ordinals (全局序数)与shard (分片)所有的字段相关联,而field data 和doc_values 与单个segment (片段)相关联.其与针对单个segment (段)相关联的特定字段的字段数据不同,一旦新的segment (片段)变得可见,Global ordinals (全局序数)就需要完全重建.
Global ordinals (全局序数)取决于一个字段上的terms (词根)数量,但通常它是比较低的.因为源字符安数据已经被加载.Global ordinals (全局序数)的内存开销很小,因为它被有效的压缩.
fielddata_frequency_filter
Fielddata 过滤可以用于减少加载到内存中 term (词根)数量,从而减少内存使用.term (词根)可以按频率来过滤 :
频率过滤器允许你仅加载 document (文档)频率在最小和最大值之间的 term (词根),可以表示为绝对数字(当数字大于1.0时)或百分比(例如0.01为1%,1.0为100%).每个segment 计算频率.百分比是基于docs (文档)的数量,而不是该segment (片段)的所有docs (文档).
通过使用 min_segment_size 指定 segment (片段)应包含的文档和最小数量,可以完全排除 small segment (小的片段),如下: