考古|search_type=count 和 scan 在 ES 5.0 被删,藏得最深的是定时任务

简介: count 从 2.0 起废弃、scan 从 2.1 起废弃,到 5.0 两个 search type 被移除。

count 从 2.0 起废弃、scan 从 2.1 起废弃,到 5.0 两个 search type 被移除。替代方式分别是 size: 0 和"按 _doc 排序的 scroll"。带这两个值的请求在 5.x 不会降级,源码里的解析会直接抛 No search type for [...]。本文对照 v5.6.16 和 v2.4.6 源码,把移除的依据、替换写法和改完以后要验证的几点写清楚。

说明

实测环境:本地起的 Elasticsearch 5.6.16 单节点实例(官方 tar 包直接跑,堆内存 512MB,外挂 JDK 8),curl 连本地 9200 端口。本文「实测」小节的命令和输出都出自这个实例;文档与源码依据仍按 v2.4.6到 v5.6.16 标签下的 search.asciidoc、search-type.asciidoc、SearchType.java 引用,哪些是文档写明、哪些是我的推断,正文里逐处标注。

01-search

图 1:官方文件 search.asciidoc(v5.6.16 标签)。来源:GitHub elastic/elasticsearch v5.6.16 search.asciidoc

官方迁移说明

5.0 迁移文档(migrate_5_0/search.asciidoc 第 8–10 行、第 47–63 行)分别写了这两项:

The count search type was deprecated since version 2.0.0 and is now removed. In order to get the same benefits, you just need to set the value of the size parameter to 0.

The scan search type was deprecated since version 2.1.0 and is now removed. All benefits from this search type can now be achieved by doing a scroll request that sorts documents in _doc order.

02-SearchType

图 2:官方文件 SearchType.java(v2.4.6 标签)。来源:GitHub elastic/elasticsearch v2.4.6 SearchType.java

count 的改法

原来:

GET /my_index/_search?search_type=count
{
   
  "aggs": {
   
    "my_terms": {
   
      "terms": {
    "field": "foo" }
    }
  }
}

改成:

GET /my_index/_search
{
   
  "size": 0,
  "aggs": {
   
    "my_terms": {
   
      "terms": {
    "field": "foo" }
    }
  }
}

2.4.6 的文档说明了 count 废弃的理由(search-type.asciidoc 第 68 行):count 相比 size 为 0 的 query_then_fetch 没有任何好处。源码里 SearchType.COUNT 的注释是同一个意思。所以这一项是纯写法替换,没有行为差别需要补偿。size: 0 的响应里 hits.total 照常存在,hits.hits 是空数组。

03-search-type

图 3:官方文件 search-type.asciidoc(v2.4.6 标签)。来源:GitHub elastic/elasticsearch v2.4.6 search-type.asciidoc

scan 的改法

GET /my_index/_search?scroll=2m
{
   
  "sort": [
    "_doc"
  ]
}

迁移文档对性能的说法是:按 _doc 排序的 scroll 已经优化过,能更高效地从上次停止的位置继续,所以和原来的 scan 有相同的性能特征。scroll 文档里也有一条 NOTE(scroll.asciidoc 第 87–89 行):不在乎顺序时,_doc 是最高效的遍历方式。

2.4.6 对 scan 的描述是"禁用排序,以便高效地滚动大结果集"(search-type.asciidoc 第 84–85 行),源码里 SearchType.SCAN 的注释写着"会自动开始滚动结果集",并注明会在 3.0 移除,应改为按 _doc 排序的常规 scroll。

请求直接失败

5.6.16 的 SearchType.fromString 第 85–96 行只认 dfs_query_then_fetch 和 query_then_fetch 两个值,其他一律抛:

No search type for [count]

对应 IllegalArgumentException,ExceptionsHelper.status 第 68–69 行把它映射成 HTTP 400。所以带 search_type=count 或 search_type=scan 的请求在 5.x 上是整个请求失败,不会降级成默认类型,也不会只出告警。REST 层请求是否正好走这条解析路径,未在集群上请求验证,以实际响应为准。

对应地,2.4.6 的 SearchType.fromString 第 127–130 行里还保留着 scan、count 两个值,由废弃标记的 ParseField 处理。这也是 2.x 期间老请求"能用"的原因:解析是通的,只是被标了废弃。

这类移除的风险在后台任务,不在在线查询

count 改起来是一行的事,在线查询一般有测试覆盖,升级后就会暴露。scan 多用在全量导出、数据迁移、重建索引这类后台任务里,平时没人盯。这些任务可能一个季度才跑一次,升级后的第一次运行才暴露失败,而那时往往正处在迁移窗口里。

所以排查范围要比线上请求宽:定时任务、运维脚本、数据同步工具里的搜索请求都要查。以下是把这两个值找出来的办法:

grep -rnE "search_type.{0,5}(count|scan)|SearchType\.(COUNT|SCAN)|searchType\(.*(COUNT|SCAN)" .

Java 客户端里是枚举常量,光搜字符串会漏,所以正则里单独写了 SearchType.COUNT、SearchType.SCAN。这是文本匹配,只能提供线索,命中以后要人看上下文。

从废弃到移除:这次的间隔

按迁移文档的说法,count 在 2.0 废弃、scan 在 2.1 废弃,到 5.0 移除。中间跨过了 2.x 的多个小版本,没有 3.x、4.x 版本(2.x 之后直接是 5.0)。废弃期间这两个值照常工作,解析通、结果对,只带一个废弃标记。

这个设计的取舍是:废弃期内不报错,保证了老应用升级小版本时不坏;代价是没有强制力,改动容易被推到最后一刻。能起作用的只有两个东西,报错,或者自己排进计划。前者在移除那一版才出现。所以我的建议是:每次大版本升级前,把"上一版已经标废弃、这一版移除"的条目单独拉出来过一遍,优先级最高,因为它们下一版就不能用了。

改完以后怎么验证

count 改 size: 0,验证三点:HTTP 200、hits.hits 为空数组、聚合结果和改之前一致。

curl -s 'localhost:9200/my_index/_search' -d '{
  "size": 0,
  "aggs": { "my_terms": { "terms": { "field": "foo" } } }
}' | python3 -m json.tool

scan 改 scroll,要多验证一步:数据有没有漏。按 scan 写的客户端逻辑和 scroll 不一样,旧代码里如果有"第一次响应只拿 _scroll_id、不处理 hits"之类的特殊处理,改成 _doc 排序的 scroll 以后,第一次响应里就有 hits,这段特殊处理会让第一批数据被跳过。本文没有在 2.4.6 上复核 scan 首次响应的具体结构,以你手上的客户端代码为准。

验证办法:挑一个小索引,用 scroll 全量拉一遍,统计拉到的 _id 数量,和 _count 的结果对比,一致再上大索引:

curl -s 'localhost:9200/small_index/_count'

另外有一条 scroll 文档里的 NOTE:请求里带聚合时,只有初始的搜索响应包含聚合结果(scroll.asciidoc 第 84–85 行附近)。如果以前靠 search_type=count 取聚合,现在换成 size: 0 的普通搜索,没有问题;但我的建议是不要把聚合和 scroll 放在一起,指望每一页都有聚合。

深分页的出口

2.1 起引入了 index.max_result_window,from + size 不能超过它,默认 10000。5.6.16 的 from-size.asciidoc 第 26–28 行仍然这么写,并指向 Scroll 和 Search After 两个更适合深翻页的方式。所以 scan 移除之后,遍历全量数据的出口是 scroll;要在界面上深翻页,用 search_after。search_after 是无状态的,每次都按最新的索引状态解析(search-after.asciidoc 第 63 行附近),和 scroll 不同,它没有快照,不适合要求一致视图的导出。把 max_result_window 调大只是推迟问题,细节见scan 废弃与 10000 上限。

取总数的几种写法

search_type=count 被移除以后,几种取总数的方式对比如下(性能差别没有实测,只列各自的做法):

目的 写法
只要总数 size: 0,读 hits.total;或者 Count API(count.asciidoc)
要聚合结果 size: 0 加 aggs
要文档 正常的 size

这三种都不需要 search_type。Count API 在 2.0 以后的失败行为有变化,见 2.0 的搜索层变更。

count 和 scan 现在是什么反应

search-type

图 4:本地 5.6.16 单节点实例上的实测输出。count 与 scan 都不存在了

curl -s "http://localhost:9200/_search?search_type=count" \
  | jq -r '.error.reason'

No search type for [count];换成 scan 是一样的结果。

失败发生在参数解析阶段,不是"查出来结果不对"——请求根本发不出去,所以迁移时不用猜行为变没变。真正要找的是还在用这两个值的地方:滚动导出、全量计数这类批处理,它们在旧版本里往往绕过了 size 限制,改的时候要连分页逻辑一起看。

写在最后

升级到 5.0 之前,把 search_type=count、search_type=scan 和对应的 Java 枚举常量找出来,count 改 size: 0,scan 改 _doc 排序的 scroll。改完用小索引核对一次数量,特别留意后台任务和定时脚本,它们最容易漏。

这次移除的做法值得借鉴:一个参数只表达一件事。取总数、遍历全量,本来就不是"搜索类型",归位到 size: 0 和 scroll 之后,search_type 剩下的 query_then_fetch 和 dfs_query_then_fetch 才是真正的检索语义。

参考

本文对照 Elasticsearch v5.6.16 标签的官方文档核对,引文逐字取自原文;文中「实测」小节的命令与输出来自本地 5.6.16 单节点实例,不含性能对比。

目录
相关文章
|
10天前
|
Linux 开发工具 iOS开发
Codex保姆级教程(下载+安装+登录+使用,含所有版本,2026最新)
Codex是OpenAI推出的开源AI编程智能体,本地运行,可理解整个代码库,支持自然语言指令改代码、执行命令、跑测试、修Bug,兼容Win/macOS/Linux。(239字)
3882 17
|
11天前
|
JavaScript API iOS开发
DeepSeek Harness下载、安装、配置一篇搞定(2026整理,送常用插件)
DeepSeek Harness(DSH)是DeepSeek于2026年开源的MIT协议AI Agent框架,支持插件化组装模型、工具、沙箱与UI,兼容主流大模型。本文提供免Node.js的桌面端安装包(Win/macOS),含详细图文教程及热门插件推荐。
4084 48
|
11天前
|
iOS开发 Docker MacOS
【2026实测】Docker Desktop下载、安装、汉化、配置教程(附官网安装包)
Docker Desktop 是 Docker 官方推出的桌面容器管理工具,集成引擎、CLI、图形界面与 Kubernetes,支持 Win/macOS/Linux。2026 最新版 4.88.1 强化 ARM 原生运行、镜像加速及资源可视化,附中文汉化与国内镜像配置指南。
1926 7
|
5天前
|
云安全 人工智能 安全
|
5天前
|
存储 弹性计算 人工智能
2026 年阿里云双十一活动入口攻略,新客服务器优惠通道、三大会场入口梳理
综合来看,2026年阿里云双十一活动入口清晰: 阿里云轻量应用服务器、阿里云ECS云服务器、阿里云GPU云服务器、阿里云百炼大模型服务平台 活动会场、综合权益中心、99计划专场三大入口覆盖服务器、AI权益与续费特价;新用户通过控制台首页banner、权益中心、产品页三处路径进入专属专场,老用户通过控制台弹窗和费用中心权益中心进入老客专区,企业用户做企业实名后解锁专属满减与阶梯折扣。
817 0
|
5天前
|
Linux 开发工具 iOS开发
2026最新codex下载安装保姆级使用教程(下载+安装+登录+使用,含所有历史版本)
本文详解OpenAI Codex国内快速上手指南:提供Win/macOS/Linux全平台免安装包、npm/Homebrew等多方式安装、账号/API Key双登录、简体中文切换,覆盖下载、安装、汉化、使用及高频避坑(如微软商店失败、npm超时等),10分钟即可跑通。
1014 2
|
11天前
|
安全 算法 定位技术
《高性价比人生指南》完整原版:普通人用最少的资源,过好这一生的底层逻辑~How To Live Better
📖《高性价比人生指南》是一份基于实证、拒绝焦虑的生存手册,倡导以“人生时薪”为视角,重新计算时间、金钱与精力的成本与收益。它不承诺逆袭,只教人算清账:省下的钱若耗掉时间便亏;买体验比买物品更值;睡眠是最高杠杆的健康投资;关系贵在情绪价值而非表面热络;学习重在改变行为而非自我安慰。核心理念:用低成本、高回报的微小行动,换取长期的选择权——不是成为谁,而是掌控自己人生的主动权。
2137 6
|
云安全 安全 网络安全
|
24天前
|
人工智能 API 开发工具
DeepSeek Harness 神插件:白嫖 13 家大厂模型
`dsh-our-free-model` 是 DeepSeek Harness 神级插件:零配置、零API Key、零账号,聚合13家大厂免费模型(含DeepSeek V4.1 Flash、Kimi K3等),支持本地网关、用量看板与自动降级,真正实现“白嫖即用”。
4268 58