bigywater.tech
Elasticsearch · 13

index、doc_values、store 分别控制什么

真实对比关闭index、关闭doc_values、同时关闭两者三种组合,验证查询和排序到底分别被哪个开关控制,发现index:false单独使用并不能让字段真正不可查询。

index:false单独使用
真实term查询照样能命中,doc_values提供后备
index+doc_values都关闭
真实查询才会直接400报错
doc_values:false单独使用
真实挡住排序聚合,不影响精确查询

做的事:真实分别关闭index、doc_values,以及同时关闭两者,对比查询和排序的真实结果

代码PUT /idx_dv_test {"mappings": {"properties": { "a_no_index": {"type": "keyword", "index": false}, "b_no_docvalues": {"type": "keyword", "doc_values": false} }}} POST .../_doc/1 {"a_no_index":"X", "b_no_docvalues":"Y"} GET .../_search {"query":{"term":{"a_no_index":"X"}}} # index关了,还能精确查到吗 GET .../_search {"sort":["b_no_docvalues"]} # doc_values关了,还能排序吗

真实出乎意料的发现:index:false的字段,term查询居然还能命中

实测 · 本机 Elasticsearch 8.15.0 执行输出
term查询 a_no_index="X"(正确值)   → hits.total.value = 1   ← 真实命中了!
term查询 a_no_index="WRONG_VALUE"(错误值) → hits.total.value = 0   ← 真实正确排除
这是本文认为最反直觉的真实发现:index:false字面意思是"不要给这个字段建倒排索引",直觉上应该意味着这个字段完全没法被查询,但本文这次真实测出term查询照样能精确命中正确的值、排除错误的值——原因是这个字段的doc_values真实保持着默认的true,Elasticsearch较新版本真实会在倒排索引缺失时,用doc_values(列式存储,本来是为排序和聚合准备的)当作精确匹配查询的后备数据源。这意味着index:false单独使用时,真实省下的只是倒排索引本身的存储和构建开销,并不能换来"这个字段彻底不可搜索"的效果——如果真实的需求是"这个字段绝对不能被任何方式查询到",光设index:false是不够的。

验证:index和doc_values真实必须同时关闭,字段才会彻底查不了

实测 · 本机执行输出
同时设index:false和doc_values:false的字段,再查:
GET .../_search {"query":{"term":{"truly_unsearchable":"X"}}}
→ 400 query_shard_exception:
  "Cannot search on field [truly_unsearchable] since it is not indexed nor has doc values."

这条真实的报错信息直接证实了上一节的推断——query_shard_exception的措辞明确区分了indexed和has doc values两件独立的事,只有这两者都真实关闭了,ES才会判定这个字段真的无法参与任何查询,直接在查询构建阶段就报错,而不是悄悄返回空结果。真实需要一个字段彻底不可查询(比如存一些只用来在应用层展示、绝不该被搜索或过滤的原始内容),必须真实同时设置index:false和doc_values:false两项,只设前者达不到效果。

验证:doc_values:false真实挡住的是排序和聚合,不是精确查询

实测 · 本机执行输出
对b_no_docvalues(doc_values:false,但index保持默认true)排序:
GET .../_search {"sort":["b_no_docvalues"]}
→ 400 illegal_argument_exception:
  "Can't load fielddata on [b_no_docvalues] because fielddata is unsupported
   on fields of type [keyword]. Use doc values instead."

但term查询b_no_docvalues="Y":真实hits.total.value = 1,照样能查到

这组对比划清了doc_values真实负责的范围:排序、聚合、脚本访问这类需要"按文档读出字段值做列式运算"的操作,底层真实依赖doc_values这份列式存储,关掉它之后,sort这类操作真实会直接报错(keyword类型连旧版本的fielddata退化方案都真实不支持,报错信息直接建议"去用doc values");但倒排索引本身没有被动过(index依然是默认的true),真实的精确匹配查询完全不受影响。三者合起来看:index管"能不能被搜索条件匹配"(但如前所述doc_values开着时有后备路径),doc_values管"能不能排序/聚合/被脚本读取",store(本文未展开,默认false,字段值由_source统一承担)管"是否在_source之外单独再保留一份这个字段的值"——三个开关真实各自独立,关闭任何一个都有真实不同的、经常被组合误解的后果。

分步演示:index:false的意外后备路径和彻底不可查询的真实条件

每一步都是本文上面在本机真实的Elasticsearch 8.15.0上跑出来的原始结果。

index/doc_values两个开关真实独立控制的能力范围
这一步新验证的开关组合

    本文用到的工具

    • 本机真实部署的 Elasticsearch 8.15.0(单节点,tar包直接启动)
    • 真实的 index / doc_values 字段级开关
    京ICP备2026067502号-1京公网安备11010502063487号