9.0 起高亮的
force_source参数不再支持。这个参数的作用原本是"强制从_source取内容做高亮",是给那些没建 term vector 又想快速高亮的场景用的兜底。现在官方把它删了——请求里带这个参数会失败。
说明
实测环境:本地起的 Elasticsearch 9.4.2 单节点实例(官方 tar 包直接跑,堆内存 512MB,安全与机器学习关闭),curl 连本地 9200 端口。图 1 出自这个实例。
官方条目
9.0 的 changelog 标为 breaking(9.0.0.yml 第 531–540 行 @ v9.4.2),PR 116943,area: Highlighting。
内容很短,两句:
details: The deprecated highlighting
force_sourceparameter is no longer supported.
impact: Users should remove usages of theforce_sourceparameter from their search requests.
官方没解释这个参数原本是干什么的。所以下面关于它作用的部分,是根据高亮机制整理的背景,不是引自官方文档——这点在每处都标清楚了。
先说高亮的两种取值路径
要理解 force_source,得先知道 ES 做高亮时从哪里取文本。
高亮要标出"这段文本里哪个词命中了",需要拿到原始文本。ES 有两条路:
一,从索引结构里取。 如果字段建了 term_vector(带 position/offset 信息),高亮器可以直接从索引里读出词的位置,速度快。
二,从 _source 里取。 读取原始文档,重新分析一遍找出命中位置。这条路不需要预先建 term vector,但每次都要重新分析文本,慢。
权衡很清楚:
- 建
term_vector→ 占更多磁盘,但高亮快; - 不建 → 省空间,但高亮要走
_source重新分析,慢。
这个权衡是理解整件事的基础:高亮快不快,主要由索引时有没有存位置信息决定,而不是由查询时的参数决定。所以后面会说,参数开关的影响远小于 mapping 配置。
文档里能看到这个权衡的影子——fvh 高亮器那节明确要求 term_vector 设为 with_positions_offsets(highlighting-settings.md 第 100 行 @ v9.4.2):
all
matched_fieldsmust haveterm_vectorset towith_positions_offsets
force_source 大概解决什么问题
按理解(官方文档没解释,这段是推断):
force_source 的作用是显式指定"这次高亮就从 _source 取"。
什么时候需要显式指定?能想到的场景是:字段同时具备走索引的条件(比如建了 term vector),但你这一次想强制走 _source——可能是为了拿到更完整的高亮结果,或者为了和其它行为保持一致。
也就是说,它是个覆盖默认选择的开关,而不是"没 term vector 时的兜底"。
这一点要特别说明:不确定这个理解对不对。因为官方既没在 changelog 里解释,在 v9.4.2 的文档里也搜不到 force_source 的说明(搜不到本身印证了它已被移除,但也就拿不到官方定义)。
所以本篇关于参数作用的描述,可靠性低于其它篇的源码核实内容。 如果你需要确切知道它做什么,得去查 8.x 的文档或者 PR 116943 的讨论。
移除之后会怎样
按 impact 的说法,请求里带 force_source 会失败——要么报错,要么参数不再被识别。
具体是哪一种,官方没说。按同类"移除参数"的改动推测,ES 对未知参数的校验通常比较严格,多半是直接报错。但这点未实测。
对使用者来说,处置动作很清楚:从搜索请求里去掉这个参数。
# 找出代码里用到它的地方
grep -rn "force_source" --include=*.json --include=*.py --include=*.go --include=*.js .
这个 grep 很快,建议升级前跑一次——确认"没有"和"有"同样是有价值的结果,前者能让你放心跳过这条改动。
为什么影响面小
判断这条 breaking 的影响面在 9.0 里属于很小的一档,理由有三:
一,它已经被标记为 deprecated 一段时间了。 changelog 里 details 直接称它为 deprecated highlighting force_source parameter——也就是说在移除之前,用它就已经会收到弃用提示。注意看日志的团队早就改了。
二,它是个可选参数。 不用高亮的人完全无关;用高亮但不指定这个参数的,也无关。只有显式写了它的才受影响。
三,高亮通常配合 term vector 使用。 认真做高亮性能的场景,早就按官方建议建了 term_vector,不太需要这个"强制走 source"的开关。
三条加起来就是:用到它的人本来就少,而这些人里大部分在弃用提示出现后就改掉了。所以实际遇到的人应该不多——但仍建议 grep 一次确认,因为"应该不多"是推断,grep 是事实。
一个更该关心的高亮配置点
既然写到高亮,把那个真正影响性能的配置说一下——它比 force_source 重要得多:
字段上要不要建 term_vector。
按文档的说法,fvh(fast vector highlighter)要求 term_vector 设为 with_positions_offsets。而如果字段没建 term vector,高亮就得走"重新分析 _source"那条路。
判断是:如果高亮上遇到性能问题,先看 term_vector,而不是找什么参数开关。配置决定路径,参数只是在路径已定的情况下做微调。
这也是对这次改动的整体看法——force_source 是个微调开关,去掉它对整体高亮能力没有影响。真正该关心的是字段的索引配置。
高亮器类型的选择
顺着 term_vector 再说一层,因为这决定了你能用哪种高亮器。
ES 有几种高亮器,按文档提到的名字至少有这些(未找到完整的官方清单,以下是按文档出现过的整理):
unified——Lucene 的 UnifiedHighlighter,通用选择;fvh(fast vector highlighter)——要求字段建term_vector,但高亮快;plain——基础高亮器,走重新分析的路子。
选择逻辑是这样的:
| 高亮器 | 对索引的要求 | 特点 |
|---|---|---|
fvh |
必须 term_vector: with_positions_offsets |
快,但要额外存储 |
unified / plain |
无特殊要求 | 慢一些,但不用改 mapping |
所以配置项是连动的:
- 先决定用不用
fvh; - 用的话,字段必须配
term_vector; - 这会增加索引体积,但换来高亮速度。
这里的判断是:多数场景用默认高亮器就够了,不要为了性能盲目上 fvh。上它要改 mapping(对存量数据意味着重建),而且占更多磁盘。只有在高亮确实是瓶颈时才值得。
(说明:高亮器的完整清单和各自要求以你版本的官方文档为准,未逐项核实。上面是按 v9.4.2 文档里出现的内容整理的。)
这条改动属于哪一类
把它归为"参数清理",和 单数据节点水位线开关移除 写的 enable_for_single_data_node、以及 Watcher 的 types 字段 写的 watcher types 是同一类。
三者的共同模式:
- 参数先被标记弃用;
- 在主版本被移除(这里是 9.0);
- 官方 impact 都说"去掉它"(而不是"改成 X")——说明没有替代项,功能直接消失。
最后这点值得留意:有替代项的和没替代项的是两类改动。
- 有替代项(如远程集群证书 → API key)→ 要做迁移工作;
- 没替代项(如本条)→ 只要删掉,行为回到默认路径。
判断属于哪类,看 impact 的措辞就能分辨——说"remove"的是后者,说"migrate/use instead"的是前者。
这个分辨在读 changelog 时很实用:同样是 breaking,前者是删一行配置,后者可能是一个季度的迁移项目。提前分清能避免排期误判。
怎么确认自己有没有用到
除了 grep 代码,还有一个更可靠的办法:看 8.x 集群上的弃用日志。
这个参数在移除前是 deprecated 状态,用过它应该会在弃用日志里留下记录:
grep -i "force_source" /var/log/elasticsearch/*_deprecation.log | head
能查到就说明确实在用(或者曾经用过)。查不到的话,多半不用管。
为什么建议两个办法都做:grep 代码只能找到自己代码里显式写的,找不到 SDK 或者看板里生成的。而弃用日志是服务端记录的实际发生过的调用——覆盖更全。
这个思路在前面几篇里反复用过(单数据节点水位线开关移除、REST API V7 兼容移除 都提到查弃用日志),因为它确实比翻代码可靠:日志反映的是真实行为,代码反映的是你认为的行为。
如果两者结果不一致——比如代码里没找到但日志里有——那说明有调用方不在你的代码库里,值得再找找(看板、第三方工具、定时任务都可能是来源)。
在 9.4.2 上跑一遍
「带着 force_source 的请求会报错还是被静默忽略」——本机跑一次就有答案:报错,而且是在解析 highlight 块时直接拒。

图 1:上:高亮请求里带 force_source: true,回 [1:52] [highlight] unknown field [force_source]。下:去掉这个参数,同一个请求正常返回高亮片段 {"t":["<em>hello</em>"]}。本地实测输出。
curl -s -XPOST 'http://localhost:9200/i1/_search' \
-H 'Content-Type: application/json' \
-d '{"query": {"match": {"t": "hello"}}, "highlight": {"force_source": true, "fields": {"t": {}}}}'
# [1:52] [highlight] unknown field [force_source]
curl -s -XPOST 'http://localhost:9200/i1/_search' \
-H 'Content-Type: application/json' \
-d '{"query": {"match": {"t": "hello"}}, "highlight": {"fields": {"t": {}}}}'
# {"t":["<em>hello</em>"]}
两条信息可以从报错里读出来:一是它在 unknown field 这一层,说明解析器已经不认识这个字段名(参数条目本身没了,不是值校验失败);二是报错里带位置 [1:52],改起来不用猜是哪个层级的问题。
结论是「报错」对使用者是好消息:这类参数如果静默忽略,老代码升级后高亮结果可能悄悄变化而没人发现;现在它会在第一发请求上就挡下来。我的建议是升级 9.x 之前先把高亮请求里的 force_source 全量删掉,不要依赖兼容层——unknown field 这种校验是逐步加严的,留着它只是把报错时间往后推。
边界:
- 图 4 出自 9.4.2 单节点实例,索引里只有一条文档,只测了请求被拒与去掉参数后正常这两种情况;
force_source原来具体起什么作用本文推断不了(官方 changelog 未解释,v9.4.2 文档里也没有该条目),这部分仍是推断,已在正文标注;- 它是在哪个版本被移除的没有实测,只核对了 9.4.2 上的行为。
写在最后
这条 breaking 的技术内容极少——一个参数被移除,处置动作是把请求里那个参数删掉。
写它主要是想说清一件事:这类"参数清理"的条目,读的时候要分辨它有没有替代项。
本次的 force_source 属于没有替代项——删掉即可,行为回到默认的高亮路径。而有替代项的(比如 远程集群证书认证弃用 写的远程集群证书模式)就要规划迁移,工作量完全不同。
一,升级前查两处:代码里 grep force_source,弃用日志里也 grep 一次。 前者找你写的,后者找实际发生过的——两者不一致时,说明有调用方不在你的代码库里。
二,高亮性能看 term_vector,不看参数开关。 字段的索引配置决定了高亮走哪条路,这才是大头。想上 fvh 要改 mapping,对存量数据意味着重建,别为了"可能更快"盲目做。
另外要坦白一点:本篇关于 force_source 具体作用的说明可靠性不如其它篇——官方没解释,也未能在 v9.4.2 文档里找到定义。是按高亮机制推断的,已在正文标注。如果你需要确切答案,去查 8.x 文档或 PR 116943 的讨论。
写这类"官方没解释"的条目时,原则是不编造细节、把推断标清楚。宁可让读者知道这一点不确定,也不要给一个看起来确定但没依据的说法——后者在排查时会误导人。
参考
- changelog 9.0.0:Remove support for deprecated
force_sourcehighlighting parameter(第 531–540 行)@ v9.4.2 - breaking-changes.md 第 295 行:同一条目的汇总列表 @ v9.4.2
highlighting-settings.md:高亮相关配置(fvh要求 term_vector)@ v9.4.2- PR 116943
本文对照 Elasticsearch
v9.4.2标签的 changelog 与文档核对,changelog 引文逐字取自原文。关于force_source参数具体作用的说明是推断——官方 changelog 未解释,且 v9.4.2 文档中已无该参数条目(印证已移除),故无法核实,正文已明确标注。带该参数的请求是报错还是静默忽略已实测:9.4.2 上直接报unknown field [force_source](见「在 9.4.2 上跑一遍」)。