当前位置: 首页 > news >正文

ES_文档

一、 文档 (Document) 的本质

1. 定义与类比

文档是 Elasticsearch 中可被索引和搜索的最小信息单元。它是以 JSON (JavaScript Object Notation) 格式表示的一个数据结构。

一个非常贴切的类比是:

  • Elasticsearch -> 一个分布式数据库
  • 索引 (Index) -> 数据库中的一张表 (Table)
  • 文档 (Document) -> 表中的一条记录 (Row)

但这个类比并不完全准确,因为 ES 的文档比关系型数据库的行更灵活、更丰富。

2. 核心特征
  • JSON 格式: 文档是序列化的 JSON 对象。JSON 的层次化、键值对结构非常适合表示复杂、半结构化的数据。
  • 可索引 (Indexable): 文档可以被 ES 分析和处理,将其中的每个字段内容转换为可搜索的倒排索引结构。
  • 唯一标识: 每个文档都有一个唯一的 ID,用于标识该文档。您可以自己指定 ID,也可以让 ES 自动生成。
  • 不可变 (Immutable): 文档一旦被索引,其内容就不能直接更改。所谓的“更新”操作,实际上是 ES 内部进行的“取回-修改-重建索引”的过程。版本号 (_version) 机制确保了在并发修改时数据的一致性。

二、 文档的组成结构

一个文档由两部分核心内容组成:

  1. 元数据 (Metadata): 描述文档本身的信息。
  2. 数据内容 (Source): 文档要存储的实际业务数据。

让我们通过一个实例来拆解。

实例:一篇新闻文章

假设我们要将一篇新闻文章存入 Elasticsearch。

原始数据:

  • 标题: “Elasticsearch 8.0 正式发布,重磅新特性详解”
  • 作者: “张三”
  • 发布日期: “2023-02-15”
  • 内容: “Elasticsearch 8.0 带来了诸多现代化提升…”
  • 标签: [“技术”, “大数据”, “搜索”]

在 Elasticsearch 中,该文档的 JSON 表示如下:

{// --- 元数据 (由 Elasticsearch 管理) ---"_index": "news-article",   // 该文档属于哪个索引"_id": "1",                 // 该文档的唯一ID,此处我们指定为1"_version": 1,              // 版本号,每次修改都会递增"_score": null,             // 相关性得分,仅在搜索时出现"_source": {                // 元数据与真实数据的“分界线”// --- 数据内容 (我们的业务数据) ---"title": "Elasticsearch 8.0 正式发布,重磅新特性详解","author": "张三","publish_date": "2023-02-15T00:00:00Z","content": "Elasticsearch 8.0 带来了诸多现代化提升...","tags": ["技术", "大数据", "搜索"],"read_count": 1500}
}

元数据字段解析:

  • _index: 文档的逻辑存储容器,所有文档必须属于一个索引。
  • _id: 文档的唯一身份证。通过 _index_id 可以唯一确定一个文档。PUT news-article/_doc/1 中的 1 就是这里指定的 ID。
  • _version: 乐观锁控制。并发修改时,如果版本号不匹配,操作会失败,防止数据覆盖。
  • _source: 这是最关键的字段。它存储了索引时传入的原始 JSON 数据。搜索时,默认返回的完整数据就来自 _source。它可以被禁用,但强烈不建议,因为很多功能(如重索引、高亮、更新)都依赖它。
  • _score: 在搜索查询时,ES 会根据匹配度计算出一个分数,表示文档与查询的相关性。

三、 文档的操作实例 (CRUD)

我们使用 Kibana Dev Tools 或 curl 来演示如何操作文档。

1. 索引一个新文档 (Create)

方式一:指定 ID

PUT news-article/_doc/1
{"title": "Elasticsearch 8.0 正式发布,重磅新特性详解","author": "张三","publish_date": "2023-02-15","content": "Elasticsearch 8.0 带来了诸多现代化提升...","tags": ["技术", "大数据", "搜索"],"read_count": 1500
}

返回结果: ES 会创建 news-article 索引(如果不存在),并在其中存储该文档,分配 ID 为 1。

方式二:自动生成 ID (推荐用于日志等场景)

POST news-article/_doc/
{"title": "另一种文章","author": "李四",...
}

返回结果: ES 会自动生成一个唯一的 ID (如 _id: "JAS12YEBfnu2nXysSapQ")。

2. 检索一个文档 (Read)
GET news-article/_doc/1

返回结果: 就是上面实例中展示的完整 JSON 结构,包括元数据和 _source 中的数据。

3. 更新文档 (Update)

注意: 如前所述,更新实质是替换。

POST news-article/_update/1
{"doc": {"read_count": 1501 // 将 read_count 增加 1}
}

ES 内部会执行:

  1. 获取 ID 为 1 的文档当前内容和版本。
  2. read_count 修改为 1501。
  3. 将整个文档重新索引到原位,并增加 _version
4. 删除文档 (Delete)
DELETE news-article/_doc/1

四、 架构师视角:文档设计的最佳实践与考量

  1. 扁平化 vs 嵌套结构

    • 尽量使用扁平化的键值对。ES 对扁平数据的处理效率更高。
    • 对于对象数组,需谨慎。例如,"tags": [“技术”, “大数据”] 是好的,因为它们是彼此独立的。
    • 如果数组中的对象需要保持其内部字段的关联性(例如"users": [ {“name”: “Alice”, “age”: 30}, {“name”: “Bob”, “age”: 25} ]),则应使用 nested 数据类型,否则会遇到“数组扁平化”问题。但这会带来性能开销。
  2. 避免过大的文档

    • _source 会被全部存储和传输。一个几 MB 的文档会消耗大量的内存、网络和磁盘 IO,严重影响集群性能。
    • 考虑将大型内容(如文章正文、Base64 图片)存储在专门的存储系统(如 S3、HDFS)中,而在 ES 文档中只保留其元数据和访问路径。
  3. 合理使用 _source 字段

    • 不要禁用 _source: 虽然可以节省磁盘空间,但你会失去更新、高亮、重建索引的能力,并且无法看到原始文档。
    • 使用 source filtering: 在搜索时,使用 _source_includes_source_excludes 来过滤返回的字段,减少网络开销。例如:GET news-article/_doc/1?_source_includes=title,author
  4. 映射 (Mapping) 先行

    • 虽然 ES 支持动态映射(自动推断字段类型),但在生产环境中,作为架构师,我们必须预先定义好映射
    • 提前定义映射可以避免 ES 推断错误的类型(例如,将 2023-01-01 推断成 text 而不是 date),并优化存储和查询性能。例如,明确 author 字段应作为 keyword 类型用于精确过滤和聚合,而不是用于全文搜索的 text 类型。
  5. 利用路由 (Routing)

    • 在分布式系统中,文档存储在哪个分片上是由 routing 值决定的,默认是 _id
    • 对于具有明显分组特性的数据(例如,所有属于某个用户的数据),在索引时指定自定义 routing(如 routing=user_id)可以将同一组数据强制存储在同一个分片上,极大地提升查询效率。

总结

对 Elasticsearch 而言,文档是其血液和灵魂。它不仅仅是存储的数据单元,更是整个倒排索引、搜索、分析的源头。深刻理解文档的结构、生命周期和设计权衡,是构建高性能、高可用性 ES 集群和应用的前提。正确的文档建模是成功的一半,而糟糕的建模则会成为系统性能和稳定性的长期瓶颈。

http://www.dtcms.com/a/342278.html

相关文章:

  • 2025-08-21 Python进阶6——迭代器生成器与with
  • Python项目开发- 动态设置工作目录与模块搜索路径
  • strerror和perror函数的使用及其联系和区别
  • 43-Python基础语法-3
  • QWidget/QMainWindow与QLayout的布局
  • CSDN使用技巧
  • Pandas中数据分组进阶以及数据透视表
  • 链表-143.重排链表-力扣(LeetCode)
  • 微信小程序集成vant-weapp时,构建npm报错的解决办法
  • 基于springboot的中医养生管理系统
  • Pytorch基础学习--张量(生成,索引,变形)
  • 火语言 RPA 进阶功能:让自动化更实用​
  • 交易高光时刻-01
  • SOP到自动化:一种适合小型金融机构的轻量级开源工具整合方案
  • Vue3+Spring Boot技术栈,前端提交混合表单数据(普通字段+文件字段),上传文件,后端插入数据,将文件保存到数据库
  • Docker端口映射与数据卷完全指南
  • 几张PPT快速了解云原生与华为云CCE方案
  • Eureka和Nacos的原理分析
  • openEuler系统中r如何将docker安装在指定目录
  • CentOS 7常用国内源配置:阿里云、腾讯云、华为云、清华源
  • 从聚类到集成,两种实用算法框架分享
  • 医疗信息化自主可控转型的实践探索 —— 以常德二院为例
  • 为什么调用API总返回404,该如何调试
  • 35、自主移动机器人 (AMR) 调度模拟 (电子厂) - /物流与仓储组件/amr-scheduling-electronics
  • 机器学习-集成算法
  • HarmonyOS 时钟应用开发详解:从零构建实时时钟组件
  • MS17-010永恒之蓝复现
  • Prometheus+Grafana 监控体系搭建:从入门到告警配置
  • open3d-点云函数:变换:旋转,缩放、平移,齐次变换(R,T)等
  • 从“卡脖子”到“自主可控”!电科金仓+东华医为生态协同,打造医疗新范式