第六阶段 51 · join 父子关系与关系建模(ES 里怎么做 JOIN)

发布时间:2026/9/23 16:01:53

第六阶段 51 · join 父子关系与关系建模(ES 里怎么做 JOIN) 51 · join 父子关系与关系建模ES 里怎么做 JOIN阶段第六阶段 / 进阶专题ESjoin字段 has_child/has_parent、反范式、terms lookup、enrich | PostgreSQLJOIN、表继承、物化视图1. 概念ES 没有真正的跨索引 JOIN这是从 PG 转过来最需要转变的观念ES 不擅长 JOIN它鼓励“用存储换查询速度”。处理关系有四条路线按推荐度方案关系落在哪适合代价反范式冗余首选写入时拍平进一篇文档关系简单、读多写少数据冗余、更新要同步nested第 25 篇同一篇文档内的数组对象主文档有限明细一起读写子项更新要重索引整篇join父子同一索引里的独立父/子文档子项需独立频繁更新、一对多量大慢、吃内存、不能跨索引terms lookup / enrich查询时/写入时做轻量关联用维表补字段有限场景一句话能反范式就别 join。join/nested 是不得已才用。2. PostgreSQL 对照-- PG跨表 JOIN 很自然SELECTo.*,c.nameFROMorders oJOINcustomers cONc.ido.customer_id;-- PG 表继承父子CREATETABLEbase_event(...);CREATETABLEclick_event()INHERITS(base_event);ES 对应跨表 JOIN →反范式把customer_name写进 order 文档或 enrich。表继承/父子 →join字段同一索引里父子文档。3.join字段父子关系3.1 mapping声明父子关系PUT orders_idx { mappings: { properties: { my_join: { type: join, relations: { order: item } // order 是父item 是子 }, order_no: { type: keyword }, sku: { type: keyword }, qty: { type: integer } } } }3.2 写入父、写入子子必须带 routing 父ID保证同分片# 父文档 PUT orders_idx/_doc/order-1 { order_no: SO-1, my_join: order } # 子文档routing 指向父parent 指定父ID PUT orders_idx/_doc/item-1?routingorder-1 { sku: A, qty: 10, my_join: { name: item, parent: order-1 } }3.3 查询has_child / has_parent# 找“包含 skuA 子项”的父订单 GET orders_idx/_search { query: { has_child: { type: item, query: { term: { sku: A } }, inner_hits: {} // 可选带出命中的子文档 } } } # 反过来找某父订单下的所有子项 GET orders_idx/_search { query: { has_parent: { parent_type: order, query: { term: { order_no: SO-1 } } } } }4. Spring Boot 实现ComponentpublicclassDoc51Join{AutowiredprivateElasticsearchClientelasticsearchClient;/** has_child找包含指定 sku 子项的父订单 */publicListMapString,ObjectparentsHavingSku(StringindexName,Stringsku)throwsIOException{SearchResponseMaprespelasticsearchClient.search(s-s.index(indexName).query(q-q.hasChild(hc-hc.type(item).query(cq-cq.term(t-t.field(sku).value(sku))).scoreMode(ChildScoreMode.None)// 不需要子分影响父分.innerHits(ih-ih))),// 带出命中的子文档Map.class);returnresp.hits().hits().stream().map(Hit::source).filter(Objects::nonNull).collect(Collectors.toList());}/** 写子文档必须带 routing 父ID */publicvoidindexChild(StringindexName,StringchildId,StringparentId,MapString,ObjectchildDoc)throwsIOException{childDoc.put(my_join,Map.of(name,item,parent,parentId));elasticsearchClient.index(i-i.index(indexName).id(childId).routing(parentId)// ★ 关键与父同分片.document(childDoc));}}importco.elastic.clients.elasticsearch._types.query_dsl.ChildScoreMode。子文档写入/查询/删除都要带routing父ID否则找不到或落错分片。5. 反范式与轻量关联更推荐的日常做法5.1 反范式首选写入时就把维表字段冗余进主文档查询零 join// order 文档直接带上客户名而不是只存 customer_id 再去 join{order_no:SO-1,customer_id:C9,customer_name:Acme,amount:1000}维表变了要同步更新冗余字段用_update_by_query第 32 篇。读多写少时这笔账很划算。5.2 terms lookup用一篇文档的值去过滤GET orders_idx/_search { query: { terms: { customer_id: { index: vip_customers, id: batch-1, path: ids // 取那篇文档的 ids 数组做 IN } } } }5.3 enrich processor写入时自动补字段在 ingest pipeline 里配 enrich policy把维表字段在写入时自动拼进文档——相当于 ETL 的 lookup join查询时就是普通字段。6. 坑与最佳实践join父子必须同索引、同分片靠routing父ID保证不能跨索引 join。父子有性能代价has_child/has_parent比普通查询慢、更吃内存量大时评估。一个索引里 join 关系尽量单一多级/多种父子会让维护和性能雪上加霜。优先反范式ES 是查询引擎不是关系库能冗余拍平就别上 join/nested。nested vs join 选型明细跟主文档一起读写 →nested子项要独立高频更新 →join。更新冗余字段用_update_by_query维表变更后批量刷新被冗余的字段。相关文档内数组对象25-nested-嵌套对象与查询.md批量刷新冗余字段32-update_by_query-delete_by_query.md索引重建改关系模型33-index-mapping-管理.md
延伸阅读

更多相关文章

2026/9/20 0:22:46

半导体精密蚀刻温控设备怎么选?阿尔西全工艺产品矩阵盘点

精密蚀刻温控是半导体制造、医疗影像诊断、数据中心及电信基础设施等高科技领域的关键支撑技术。蚀刻温控系统通过精确管理工艺设备的发热与散热过程,确保温度波动控制在极窄范围内,从而保障产品良率、设备稳定运行及能源利用效率。阿尔西集团&#xff0…

2026/9/23 15:59:25

黄正备考避坑:3个底层逻辑助你拿下面试必问难题

黄正备考避坑:3个底层逻辑助你拿下面试必问难题 刚背完规范却还在现场瞎指挥?黄正考试里那些看似死记硬背的条款,其实全是工程现场的“生存法则”。很多兄弟觉得《公路工程》教材厚如砖头,读完就忘,一到面试必问的实操题就卡壳,根源就在于你只学了“语…

2026/9/23 15:59:25

PLM不是网盘:构建研发项目状态驱动型执行体系

简介:本资源是一份面向制造业研发管理者、PLM实施顾问及技术型项目经理的实战型管理课件,聚焦如何依托PLM平台构建结构化、协同化、市场驱动的研发项目管理体系,系统应对需求多变、周期缩短、跨学科协作与团队规模化等核心挑战。课件为单文件…

2026/9/23 15:59:25

文化衫设计模板源码解析:3步搞定前端排版报错

文化衫设计模板源码解析:3步搞定前端排版报错 刚接手公司年会文化衫定制项目,打开 Figma 导出代码,页面直接崩了。控制台里飘着红彤彤的报错,一堆 TypeError: Cannot read properties of…

2026/9/23 15:59:25

DeepSeek跨框架迁移实战:PyTorch到TensorFlow对齐指南

简介:本资源是一份面向深度学习工程师与大模型研发人员的实战型技术指南,系统解决DeepSeek开源模型在PyTorch与TensorFlow双框架间迁移训练的核心难题。全书197页、48章,覆盖环境配置、代码模块拆解、网络结构重构、算子映射对照、动态图转静…

2026/9/23 15:54:25

三万英尺等于多少米?开发者的单位换算速查手册

三万英尺等于多少米?开发者的单位换算速查手册 看了一堆教程还是不会写项目?别慌,很多时候卡住你的不是高深的架构,而是那些看似基础却极易出错的细节。今天咱们不聊虚的,直接拆解一个在面试和实际业务中经常“阴人”的小知识点: 三万英尺等于多少米…

2026/9/23 12:07:00

GAMP 5 基于风险的计算机化系统验证:软件分类与审计追踪实践

简介:《A Risk-Based Approach to Compliant GxP Computerized Systems》即业内熟知的GAMP 5指南,面向制药企业质量与IT合规人员、验证工程师及计算机化系统管理者,用于解决GxP法规环境下系统合规性难以科学落地的问题。文档以风险管理为主线…

2026/9/23 12:06:55

安全托管MSSP实战:从静态防御到人机协同的攻防运营与应急响应

简介:这份PPT围绕互联网业务安全托管服务展开,面向企业安全负责人、IT运维人员及关注MSSP/MSS选型的读者,重点回应传统安全过度依赖人工、碎片化静态防御难以对抗产业化攻击等痛点。资源共1个pptx文件,包体约30.63MB,以…

2026/9/23 0:01:54

3个实战技巧搞定形式英语:从看教程到跑通性能优化

3个实战技巧搞定形式英语:从看教程到跑通性能优化 看了一堆教程还是不会写项目?别慌,这种“眼高手低”的困境在开发者圈子里太常见了。很多人以为卡点在语法,其实真正拦路虎是缺乏将知识点串联成完整链路的能力。今天咱们不聊虚的,直接拿【形式英语】这…

2026/9/22 16:34:32

USB Type-C PCB布局分区设计:电源、高速信号与PD协议全攻略

做硬件这行,Type-C接口算是典型的“看着简单,做起来全坑”的东西。光引脚就24个,高低速信号、电源、控制线全部塞在一个小小的连接器里,如果PCB布局不做规划,打样回来基本就是“插上没反应”、“高速掉线”、“静电一打…

2026/9/22 20:01:30

系统编程学习原型如何补齐稳定性边界

系统编程学习原型如何补齐稳定性边界预算有限时&#xff0c;我先优化明显多余的复制&#xff0c;而不是猜测性地换容器。用借用传递只读数据通常就能减少分配&#xff1a; fn parse(line: &str) -> Result<Item, Error> { /* ... */ }用基准确认热点确实在分配&am…

2026/9/22 13:25:41

雨花区哪家财务公司代理记账比较好?

在雨花区&#xff0c;企业处理财税事务常常面临诸多挑战&#xff0c;选择一家靠谱的财务公司至关重要。湖南巨勤财务管理咨询有限公司就是本地正规实体财税服务机构&#xff0c;深耕本地工商财税行业多年&#xff0c;熟悉当地工商局、税务局最新政策与申报流程。主营公司注册、…

还想了解更多?直接咨询顾问

免费诊断 + 免费方案 + 透明报价。

全国咨询热线400-8866-253
免费获取方案
咨询二维码