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

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

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

谢谢支持哟 ( ^__^ )。

相关推荐
追逐时光者1 小时前
精选 5 款 .NET 开源、功能强大的工作流系统,告别重复造轮子!
后端·.net
bobz9652 小时前
Agent AI:多模态交互前沿调查
后端
小厂永远得不到的男人2 小时前
一篇文章搞懂 java 反射
java·后端
蒋星熠2 小时前
Rust 异步生态实战:Tokio 调度、Pin/Unpin 与零拷贝 I/O
人工智能·后端·python·深度学习·rust
David爱编程2 小时前
Java 编译期 vs 运行期:避开这些坑,少掉一半 Bug
java·后端
麦兜*3 小时前
Spring Boot调用优化版AI推理微服务 集成 NVIDIA NIM指南
java·人工智能·spring boot·后端·spring cloud·微服务·ai编程
Moonbit4 小时前
# 量子位 AI 沙龙回顾丨用 MoonBit Pilot 解答 AI Coding 的未来
后端
码事漫谈4 小时前
C++ vector越界问题完全解决方案:从基础防护到现代C++新特性
后端
啾啾大学习5 小时前
让我们快速入门DDD
后端·领域驱动设计