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

【Elasticsearch】映射:Join 类型、Flattened 类型、多表关联设计

映射:Join 类型、Flattened 类型、多表关联设计

  • 1.Join 类型
    • 1.1 主要应用场景
      • 1.1.1 一对多关系建模
      • 1.1.2 多层级关系建模
      • 1.1.3 需要独立更新子文档的场景
      • 1.1.4 文档分离但需要关联查询
    • 1.2 使用注意事项
    • 1.3 与 Nested 类型的区别
  • 2.Flattened 类型
    • 2.1 实际运用场景和案例
      • 2.1.1 日志数据处理
      • 2.1.2 用户自定义属性
      • 2.1.3 API 请求/响应存储
      • 2.1.4 第三方数据集成
    • 2.2 不足之处
    • 2.3 与 Nested / Object 类型的对比
  • 3.多表关联设计方案
    • 3.1 嵌套对象(Nested Objects)
    • 3.2 父子文档(Parent-Child Relationship)

1.Join 类型

在 Elasticsearch 中,Join 类型是一种特殊的数据类型,用于在文档之间建立 父子关系嵌套关系。它允许你在索引中创建类似于关系型数据库中的表连接(join)效果。

Join 类型主要通过以下两个字段实现:

  • join_field:定义关系的字段。
  • relations:指定父子关系的映射。

1.1 主要应用场景

1.1.1 一对多关系建模

当需要表示一个父文档对应多个子文档时,例如:

  • 博客文章(父)、评论(子)
  • 订单(父)、订单项(子)
PUT my_index
{"mappings": {"properties": {"join_field": {"type": "join","relations": {"post": "comment"}}}}
}

1.1.2 多层级关系建模

需要表示多层级的树形结构,例如:

  • 组织架构(公司 → 部门 → 员工)
  • 产品分类(大类 → 中类 → 小类)
PUT my_index
{"mappings": {"properties": {"join_field": {"type": "join","relations": {"company": ["department", "employee"],"department": "employee"}}}}
}

1.1.3 需要独立更新子文档的场景

  • 场景:当子文档需要频繁独立更新,而父文档相对稳定时。
  • 优势:可以单独更新子文档,而不影响父文档。

1.1.4 文档分离但需要关联查询

  • 场景:文档逻辑上属于不同实体但需要联合查询。
  • 示例
    • 用户基本信息(父)、用户行为日志(子)。
    • 产品信息(父)、产品价格历史(子)。

1.2 使用注意事项

  • 性能考虑:Join 查询通常比普通查询更耗资源。
  • 分片限制:父子文档必须存储在同一个分片上。
  • 替代方案:对于简单关系,考虑使用 nested 类型或应用层处理。
  • 适用版本:Elasticsearch 5.x 及以上版本支持。

1.3 与 Nested 类型的区别

特性Join 类型Nested 类型
存储方式独立文档同一文档内嵌
更新灵活性可单独更新子文档需要更新整个文档
查询性能相对较慢相对较快
适用场景大量子文档、频繁更新少量子文档、不常更新

Join 类型为 Elasticsearch 提供了处理复杂关系的灵活性,但应根据具体场景权衡使用,因为它在查询性能和资源消耗上会有一定代价。

2.Flattened 类型

Flattened 类型是 Elasticsearch 7.3 版本引入的一种特殊数据类型,主要用于解决以下核心问题:

  • 动态字段爆炸问题:当索引包含大量不可预知的动态字段时,会导致映射膨胀,影响集群性能。
  • 非结构化数据处理:处理 JSON 文档中未知或高度动态的结构时,避免为每个字段创建独立映射。
  • 降低存储开销:减少为大量稀疏字段维护倒排索引的开销。

2.1 实际运用场景和案例

2.1.1 日志数据处理

  • 场景:处理不同来源、格式各异的日志数据。
  • 案例:集中收集不同应用的日志,各应用日志字段结构不同,且可能随时变化。
PUT logs_index
{"mappings": {"properties": {"log_data": {"type": "flattened"}}}
}

2.1.2 用户自定义属性

  • 场景:电商平台中商品的扩展属性。
  • 案例:不同类别的商品有完全不同的属性集,且卖家可自定义添加属性。
PUT products
{"mappings": {"properties": {"custom_attrs": {"type": "flattened"}}}
}

2.1.3 API 请求/响应存储

  • 场景:记录微服务间通信的请求和响应。
  • 案例:不同服务的 API 结构差异大,且版本迭代会导致结构变化。
PUT api_monitor
{"mappings": {"properties": {"request": {"type": "flattened"},"response": {"type": "flattened"}}}
}

2.1.4 第三方数据集成

  • 场景:集成来自多个第三方来源的数据。
  • 案例:从不同社交平台获取用户数据,各平台数据结构迥异。

2.2 不足之处

  • 查询功能限制
    • 不支持精确的 term 查询,只能使用 prefixwildcard 等有限查询方式。
    • 无法对 flattened 字段中的单个子字段进行独立聚合。
  • 搜索性能影响
    • 相比常规字段,flattened 字段的查询性能较低。
    • 不支持相关性评分(scoring),所有匹配文档得分相同。
  • 存储效率问题
    • 虽然减少了映射膨胀,但存储空间可能比精心设计的映射更大。
    • 所有子字段值被索引为关键字,不进行文本分析。
  • 功能缺失
    • 不支持多字段(multi-fields)特性。
    • 不能指定不同的分析器或分词器。
  • 排序限制
    • 不能直接对 flattened 字段进行排序操作。

2.3 与 Nested / Object 类型的对比

特性Flattened 类型Nested 类型Object 类型
字段映射膨胀完全避免可能发生可能发生
查询灵活性有限完全支持完全支持
存储效率中等较低(重复元数据)较高
适合场景未知 / 动态字段固定结构的数组对象固定结构的嵌套对象
支持子字段独立查询 / 聚合不支持支持支持

Flattened 类型是 Elasticsearch 为特定场景提供的折中方案,它在灵活性和功能完整性之间做了平衡。当面对高度动态、不可预测的数据结构时,它提供了可行的解决方案,但需要清楚其局限性。

3.多表关联设计方案

在 Elasticsearch 中,由于它是面向文档的 NoSQL 数据库,不像关系型数据库那样原生支持 JOIN 操作,因此需要采用特殊的设计方案来实现多表关联。以下是常见的两种方案:

3.1 嵌套对象(Nested Objects)

  • 场景:适用于一对多关系,子对象数量较少且不经常独立查询的场景。
  • 案例:博客文章与评论。
PUT /blog_index
{"mappings": {"properties": {"title": { "type": "text" },"author": { "type": "keyword" },"comments": {"type": "nested", "properties": {"username": { "type": "keyword" },"content": { "type": "text" },"timestamp": { "type": "date" }}}}}
}

查询嵌套对象:

GET /blog_index/_search
{"query": {"nested": {"path": "comments","query": {"bool": {"must": [{ "match": { "comments.content": "Elasticsearch" }},{ "match": { "comments.username": "john" }}]}}}}
}

3.2 父子文档(Parent-Child Relationship)

  • 场景:适用于一对多关系,子对象数量大或需要独立查询的场景。
  • 案例:订单与订单项。
PUT /order_index
{"mappings": {"properties": {"order_id": { "type": "keyword" },"order_date": { "type": "date" },"customer_id": { "type": "keyword" },"relation_type": { "type": "join","relations": {"order": "item" }}}}
}

在这里插入图片描述

添加父文档(订单):

PUT /order_index/_doc/1
{"order_id": "ORD001","order_date": "2023-01-01","customer_id": "CUST123","relation_type": {"name": "order"}
}

在这里插入图片描述

添加子文档(订单项):

PUT /order_index/_doc/2?routing=1
{"product_id": "PROD456","quantity": 2,"price": 19.99,"relation_type": {"name": "item","parent": "1" }
}

在这里插入图片描述

查询子文档:

GET /order_index/_search
{"query": {"has_parent": {"parent_type": "order","query": {"match": { "customer_id": "CUST123" }}}}
}

在这里插入图片描述

其他方案还包括:

  • 应用层关联:先查询一个索引,再根据结果查询另一个索引。
  • 数据冗余:将关联数据冗余存储在主文档中。
  • 宽表模式:在索引时预先关联好数据。

选择哪种方案取决于查询模式、数据更新频率和性能要求。

http://www.lqws.cn/news/211609.html

相关文章:

  • IDEA中的debug使用技巧
  • 代码注释类型
  • 0基础破解Typora,使用正版已激活Typora
  • 柯尼卡美能达Konica Minolta bizhub 205i打印机信息
  • 【20250607接单】Spark + Scala + IntelliJ 项目的开发环境配置从零教学
  • 红队实战全流程:从外部侦察到域控征服的内网渗透 >>> 检测一下小伙伴自己的道行哟
  • 【Java学习笔记】String类(重点)
  • 数论总结,(模版与题解)
  • [特殊字符] 深入理解 Linux 内核进程管理:架构、核心函数与调度机制
  • JAVA理论第四战-线程池
  • 动态可写的四层路由利器ngx_stream_keyval_module
  • WSF07N10 MOSFET 在铲皮机中的应用
  • 【西门子杯工业嵌入式-3-如何使用KEY】
  • 垃圾回收相关八股
  • Redis内存淘汰策略
  • 【Linux】LInux下第一个程序:进度条
  • 东芝Toshiba e-STUDIO2110AC打印机信息
  • 数据结构算法(C语言)
  • Ctrl-Crash 助力交通安全:可控生成逼真车祸视频,防患于未然
  • 基于 Transformer robert的情感分类任务实践总结之二——R-Drop
  • altium designer2024绘制stm32过程笔记x`
  • WebRTC通话原理与入门难度实战指南
  • 从零开始制作小程序简单概述
  • Oracle 审计参数:AUDIT_TRAIL 和 AUDIT_SYS_OPERATIONS
  • SDC命令详解:使用set_port_fanout_number命令进行约束
  • AIGC的产品设计演进:从工具到协作者
  • 生成模型从自回归到变分自动编码器
  • 提供MD5解密的网站
  • WaytoAGI东京大会开启AI全球化新对话:技术无国界,合作促创新
  • 虚拟主机都有哪些应用场景?