Elasticsearch文档数迷思:深度解析count与stats背后机制

一、问题现象:同一个索引文档数为何不同

统计文档数量有两种方式,一个是count API,另一个是stats API。

此处拿测试索引来举例。

bash 复制代码
## 查询商品索引文档数
GET /test_index/_count          --> 返回 33535
{
  "count": 33535,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  }
}
GET /test_index/_stats/docs    --> 显示 "docs": { "count": 150639 }
{
.....
      "total": {
        "docs": {
          "count": 150639,
          "deleted": 866
        }
}

两个 API返回的结果竟然不同,是 bug 吗?

二、count与_stats的本质区别

2.1 _count

_count 统计给定查询的文档数量。

_count只统计主文档,不统计嵌套类型的子文档。

2.2 _stats

_stats 统计所有的 Lucene 文档,包括主文档和 nested 类型的所有子文档。

通过 level 可以控制统计层级,参数【cluster/indices/shards】控制统计层级(集群/索引/分片)。

默认返回的是 indices 级别。

bash 复制代码
GET /test_nested/_stats/docs?level=indices
GET /test_nested/_stats/docs

三、示例演示

3.1、创建一个包含nested 类型的索引

json 复制代码
PUT /test_nested
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested",  // 定义 nested 类型字段
        "properties": {
          "name": { "type": "keyword" }
        }
      }
    }
  }
}

3.2、插入一个文档,包含两个nested类型的子文档

json 复制代码
POST /test_nested/_doc/1
{
  "user": [
    { "name": "zuiyujava" },  // nested 子文档1
    { "name": "zuiyupython" }     // nested 子文档2
  ]
}

3.3、使用count API 查看

bash 复制代码
GET /test_nested/_count
​
返回
{
  "count": 1,
  "_shards": {
    "total": 1,
    "successful": 1,
    "skipped": 0,
    "failed": 0
  }
}

3.4、使用stats API查看

json 复制代码
GET /test_nested/_stats/docs
 
​
返回
{
    "test_nested": {
      "uuid": "AiQv1B75SImtSjLPO-hlvA",
      "health": "yellow",
      "status": "open",
      "primaries": {
        "docs": {
          "count": 3,
          "deleted": 0
        }
      },
      "total": {
        "docs": {
          "count": 3,   // 主文档1 + nested子文档2 = 3
          "deleted": 0
        }
      }
}

四、解决

首先是使用refresh 刷新索引,防止数据还没有完全刷新到磁盘或者Lucene索引中。 其次是理解_count_stats 的区别,如果是因为nested 嵌套字段引起的文档数量不一致,可以考虑使用flattened类型。

五、总结

_count用于查询索引中匹配给定查询的文档数量

_stats 统计的是 Lucene 级别的文档数,包括索引中的所有原始文档和嵌套字段所产生的文档数量。 明确区分_count_stats的使用场景,避免在_count中滥用通配符查询。

Elasticsearch的文档数不是简单的数字,而是分布式系统复杂性的缩影。理解其内在机制,方能避免被表象迷惑。

(本文实验数据基于Elasticsearch 8.11版本,部分命令需调整后兼容老版本)

最后补充一下API的使用

_count

获取与查询匹配的文档数量。

查询可以通过使用简单的查询字符串作为参数来提供,也可以通过在请求正文中定义查询 DSL 来提供。查询参数是可选的。如果未提供查询参数,API 将用于match_all统计所有文档。

_count API 支持多目标语法。可以跨多个数据流和索引运行单个计数 API 搜索。

该操作会在所有分片上广播。对于每个分片 ID 组,都会选择一个副本并针对该副本运行搜索。也就是说可以使用副本提高计数的可扩展性。

所需要的权限:read

参考官网地址:www.elastic.co/docs/api/do...

_stats

返回索引统计信息。

对于数据流,API 会检索流的支持索引的统计信息。

所需要的权限:monitor

参考官网地址:www.elastic.co/docs/api/do...
公众号:醉鱼Java

如果这篇文章对您有所帮助或者启发,帮忙点个关注叭,您的支持是我坚持写作的最大动力。

求一键三连:点赞、收藏、关注。

谢谢支持哟 ( ^__^ )。

相关推荐
SimonKing8 分钟前
大V说’AI替代不了你’,但现实是——用AI的人正在替代你
java·后端·程序员
IT_陈寒9 分钟前
SpringBoot里的这个坑差点让我加班到天亮
前端·人工智能·后端
BingoGo1 小时前
Laravel13 + Vue3 的免费可商用 PHP 管理后台 CatchAdmin V5.2.0 发布
后端·php·laravel
rannn_1111 小时前
【Redis|高级篇1】分布式缓存|持久化(RDB、AOF)、主从集群、哨兵、分片集群
java·redis·分布式·后端·缓存
weixin_408099671 小时前
【实战教程】EasyClick 调用 OCR 文字识别 API(自动识别屏幕文字 + 完整示例代码)
前端·人工智能·后端·ocr·api·安卓·easyclick
添尹1 小时前
Go语言基础之指针
开发语言·后端·golang
GreenTea10 小时前
一文搞懂Harness Engineering与Meta-Harness
前端·人工智能·后端
我是大猴子12 小时前
Spring代理类为何依赖注入失效?
java·后端·spring
码事漫谈12 小时前
手把手带你部署本地模型,让你Token自由(小白专属)
前端·后端
码农BookSea14 小时前
ReAct:让大模型学会边想边做
后端·ai编程