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

ElasticSearch深入解析(九):Object、Nested、Flattened类型

文章目录

      • 一、Object 类型:默认的嵌套对象处理方式
        • 核心原理
        • 典型场景
        • 关键限制
      • 二、Nested 类型:解决嵌套数组的关联查询
        • 核心原理
        • 典型场景
        • 使用示例
        • 注意事项
      • 三、Join 类型:跨文档的父子关联
        • 核心原理
        • 典型场景
        • 使用示例
        • 注意事项
      • 四、Flattened 类型:动态嵌套对象的轻量化处理
        • 核心原理
        • 典型场景
        • 使用示例
        • 注意事项
      • 五、类型对比与选择建议

Elasticsearch 作为面向文档的搜索引擎,对嵌套数据的处理有多种方式,不同类型适用于不同的业务场景。

一、Object 类型:默认的嵌套对象处理方式

核心原理

Elasticsearch 中,JSON 文档的嵌套对象(如 {"user": {"name": "张三", "age": 25}})会被默认映射为 Object 类型。其底层通过 字段扁平化 实现索引:将嵌套对象的字段展开为 父字段.子字段 的形式(如 user.nameuser.age),存储为独立的字段。

典型场景

适用于 简单嵌套对象,且不需要对嵌套对象内部字段进行 关联查询 的场景。例如:

{"article": {"title": "ES 数据类型指南","author": { "name": "李四", "email": "lisi@example.com" }}
}

此时 author 是一个简单对象,若只需查询 author.nameauthor.email 的独立值(不关心是否属于同一作者),Object 类型足够。

关键限制

当嵌套对象是 数组 时(如一个用户有多个地址),Object 类型会 丢失对象内部字段的关联。例如:

{"user": "张三","addresses": [{"city": "北京", "zip": "100000"},{"city": "上海", "zip": "200000"}]
}

Elasticsearch 会将 addresses.city 存储为 ["北京", "上海"]addresses.zip 存储为 ["100000", "200000"]。若执行查询 city=北京 AND zip=200000,会错误匹配到这条文档(因为字段被扁平化,不关心“北京”和“200000”是否属于同一个地址对象)。

二、Nested 类型:解决嵌套数组的关联查询

核心原理

Nested 类型是 Object 类型的扩展,专门用于处理 嵌套对象数组。它将数组中的每个对象 独立索引为一个“子文档”,保留对象内部字段的关联关系。查询时需使用 nested 查询,确保只匹配同一嵌套对象内的字段。

典型场景

适用于 一对多关联 且需要对嵌套对象内部字段进行 组合查询 的场景。例如:

  • 订单的多个商品(需查询“购买了苹果手机且数量>2的订单”);
  • 用户的多个地址(需查询“城市为北京且邮编为100000的地址”)。
使用示例

映射定义

PUT /my_index
{"mappings": {"properties": {"user": {"type": "nested",  // 指定为 nested 类型"properties": {"name": {"type": "keyword"},"address": {"type": "nested",  // 支持多层嵌套"properties": {"city": {"type": "keyword"},"zip": {"type": "keyword"}}}}}}}
}

查询示例(匹配同一地址内的城市和邮编):

GET /my_index/_search
{"query": {"nested": {"path": "user.address",  // 指定嵌套路径"query": {"bool": {"must": [{"term": {"user.address.city": "北京"}},{"term": {"user.address.zip": "100000"}}]}}}}
}
注意事项
  • 性能与存储:每个嵌套对象独立索引,会增加索引体积(约为普通 Object 类型的 1.5~3 倍);
  • 嵌套层级:支持多层嵌套(如 user.address.street),但深度建议不超过 5 层(过深会影响查询性能);
  • 更新限制:修改嵌套对象的任意字段需重新索引整个父文档(类似关系型数据库的级联更新)。

三、Join 类型:跨文档的父子关联

核心原理

Join 类型允许在 同一索引 中建立父子文档关系(如父文档是“用户”,子文档是“用户的订单”)。通过 _parent 字段关联父子文档,父文档和子文档需存储在 同一分片 上(通过父文档的 _id 哈希到分片)。

典型场景

适用于 跨文档的一对多关联,且父子文档需要 独立更新 的场景。例如:

  • 论坛的“板块(父)- 帖子(子)”;
  • 企业的“部门(父)- 员工(子)”。
使用示例

映射定义

PUT /my_index
{"mappings": {"properties": {"join_field": { "type": "join","relations": {"department": "employee"  // 父类型: "department",子类型: "employee"}}}}
}

创建父文档(部门)

PUT /my_index/_doc/1
{"name": "技术部","join_field": { "name": "department" }  // 标记为父类型
}

创建子文档(员工)

PUT /my_index/_doc/2?routing=1  // 必须与父文档同分片(routing=父文档ID)
{"name": "张三","join_field": { "name": "employee", "parent": "1"  // 关联父文档ID}
}

查询示例(查询技术部的所有员工):

GET /my_index/_search
{"query": {"has_parent": {"parent_type": "department","query": { "term": { "name": "技术部" } }}}
}
注意事项
  • 性能瓶颈:父子查询需要跨文档关联(类似关系型数据库的 JOIN),性能低于 Nested 类型(Nested 是单文档内的关联);
  • 分片限制:父文档和子文档必须同分片,若父文档分布不均可能导致分片数据倾斜;
  • 适用场景:仅当父子文档需要 独立更新(如父文档修改不影响子文档)时使用,否则优先选择 Nested 类型。

四、Flattened 类型:动态嵌套对象的轻量化处理

核心原理

Flattened 类型用于将 复杂的嵌套 JSON 对象(如动态结构的元数据)展平为单个字段。所有嵌套的键会被合并为 点分隔的字符串(如 {"a": {"b": "c"}} 会被展平为 a.b: c),并索引为 keyword 类型(支持精确匹配)。

典型场景

适用于 动态或未知结构的嵌套对象,例如:

  • 日志中的 tags 字段(可能包含任意层级的键值对);
  • 商品的扩展属性(如不同品类的额外信息)。
使用示例

映射定义

PUT /my_index
{"mappings": {"properties": {"metadata": {"type": "flattened"  // 指定为 flattened 类型}}}
}

文档示例

PUT /my_index/_doc/1
{"metadata": {"user": {"name": "张三","age": 25},"device": "iPhone 15"}
}

此时 metadata 会被展平为 metadata.user.name: "张三"metadata.user.age: "25"metadata.device: "iPhone 15" 等字段。

查询示例(精确匹配展平后的路径):

GET /my_index/_search
{"query": {"term": { "metadata.user.name": "张三" }  // 直接使用展平后的字段名}
}
注意事项
  • 字段限制:展平后的字段数量默认最多 1000 个(可通过 max_flattened_fields 参数调整);
  • 查询能力:仅支持精确匹配(term)或前缀匹配(prefix),无法进行范围查询(如 age>20);
  • 适用场景:优先用于 不需要复杂查询 的动态嵌套对象(如日志元数据),避免因动态映射导致字段爆炸。

五、类型对比与选择建议

类型核心特点适用场景性能与限制
Object扁平化存储,丢失嵌套对象关联简单嵌套对象,无需关联查询轻量,无法处理嵌套数组的关联查询
Nested独立索引嵌套对象,保留关联一对多嵌套数组,需关联查询索引体积大,更新成本高
Join跨文档父子关联父子需独立更新,跨文档查询查询性能差,分片限制严格
Flattened展平动态嵌套对象,简化索引动态/未知结构的嵌套对象,轻查询仅支持精确匹配,字段数量受限

选择建议

  1. 优先使用 Nested 类型 处理嵌套数组的关联查询(如订单-商品);
  2. 仅当父子需独立更新时使用 Join 类型(如部门-员工);
  3. 动态或未知结构的嵌套对象用 Flattened 类型(如日志元数据);
  4. 简单嵌套对象且无需关联查询时,使用默认的 Object 类型
http://www.xdnf.cn/news/3622.html

相关文章:

  • 【RabbitMQ】 RabbitMQ快速上手
  • Python 函数装饰器和闭包(使用装饰器改进“策略”模式)
  • 玩转Docker | 使用Docker部署AI证件照工具
  • 【2025】ORM框架是什么?有哪些常用?Mybatis和Hibernate是什么样的?
  • ES6/ES11知识点
  • wpf CommandParameter 传递MouseWheelEventArgs参数 ,用 MvvmLight 实现
  • Word域操作记录(从1开始的毕业论文格式排版)
  • 神经网络的基本概念与深度解析——基于生物机制的仿生建模与工程实现
  • Spring Boot的GraalVM支持:构建低资源消耗微服务
  • Kubernetes(k8s)学习笔记(四)--入门基本操作
  • 双指针(5)——有效三角形个数
  • 杭电oj(1180、1181)题解
  • “淘宝闪购”提前4天全量,意味着什么?
  • 传奇各职业/战士/法师/道士/手套/手镯/护腕/神秘腰带爆率及出处产出地/圣战/法神/天尊/祈祷/虹魔/魔血
  • Demo02_基于寄存器+标准库开发的项目
  • 传奇各职业/战士/法师/道士/戒指爆率及出处产出地/圣战/法神/天尊/虹魔/魔血/麻痹/超负载/求婚/隐身/传送/复活/护身/祈祷/火焰
  • Linux系统常用命令、标准C库函数和系统调用
  • new和malloc的区别
  • 一场陟遐自迩的 SwiftUI + CoreData 性能优化之旅(上)
  • Redis总结及设置营业状态案例
  • 泰迪杯特等奖案例学习资料:基于CLIP模型微调与知识蒸馏的多模态图文检索系统设计
  • B站Michale_ee——ESP32_IDF SDK——FreeRTOS_7 流数据缓冲区、消息缓冲区
  • Python基于深度学习的网络舆情分析系统(附源码,部署)
  • 基于蒙特卡洛模拟的电路容差分析与设计优化
  • 倒排索引与数据库索引
  • 拆解一个550-800Mhz的LC滤波器内部大图配测试曲线
  • 这款软件的第三方评测:功能、易用性与性能表现如何?
  • 链表系列一> K 个一组翻转链表
  • wsl安装
  • 自动化测试项目2 --- 比特纵横 [软件测试实战 Java 篇]