
点击蓝字关注我们
Elasticsearch 作为 NoSQL 数据库,不直接支持传统关系型数据库(如 MySQL)的 JOIN 操作,但通过 8.18 版本引入的 ES|QL LOOKUP JOIN(技术预览)以及其他方式(如嵌套文档、父子关系),可以实现类似功能。以下以一个具体场景为例,展示实现方法。
场景描述
索引:
users:存储用户信息(user_id, user_name)。
orders:存储订单信息(order_id, user_id, order_amount)
目标:查询每个用户的订单信息,类似 MySQL 的
•SELECT * FROM users JOIN orders ON users.user_id = orders.user_id
方法一:使用 ES|QL 的 LOOKUP JOIN
1. 准备索引和数据
创建并填充 users 和 orders 索引:
创建 users 索引
PUT users{"mappings": {"properties": {"user_id": {"type": "keyword"},"user_name": {"type": "text"}}}}
插入 users 数据
POST users/_doc{ "user_id": "u1", "user_name": "Alice" }POST users/_doc{ "user_id": "u2", "user_name": "Bob" }
创建 orders 索引
PUT orders{"mappings": {"properties": {"order_id": {"type": "keyword"},"user_id": {"type": "keyword"},"order_amount": {"type": "float"}}}}
插入 orders 数据
POST orders/_doc{ "order_id": "o1", "user_id": "u1", "order_amount": 100.50 }POST orders/_doc{ "order_id": "o2", "user_id": "u1", "order_amount": 200.75 }POST orders/_doc{ "order_id": "o3", "user_id": "u2", "order_amount": 50.25 }
2. 执行 LOOKUP JOIN 查询
使用 ES|QL 实现关联查询:
POST _query?format=txt{"query": """FROM users |LOOKUP orders ON users.user_id = orders.user_id |KEEP user_id,user_name,order_id,order_amount """}
3. 输出结果
user_id | user_name | order_id | order_amount--------|-----------|----------|-------------u1 | Alice | o1 | 100.50u1 | Alice | o2 | 200.75u2 | Bob | o3 | 50.25
4. 特点与注意事项
行为:类似 MySQL 的 INNER JOIN,仅返回匹配记录。若需 LEFT JOIN 效果,需额外处理空值。
适用场景:适合中小规模数据关联,快速构建跨索引查询。
限制:LOOKUP JOIN 为技术预览功能,生产环境需测试稳定性。复杂嵌套字段或多对多关系可能受限。
版本要求:Elasticsearch 8.18 或更高版本。
方法二:使用嵌套文档
1. 索引设计
将 orders 嵌入 users 文档,使用 nested 字段类型:
PUT users{"mappings": {"properties": {"user_id": {"type": "keyword"},"user_name": {"type": "text"},"orders": {"type": "nested","properties": {"order_id": {"type": "keyword"},"order_amount": {"type": "float"}}}}}}
插入数据
POST users/_doc{"user_id": "u1","user_name": "Alice","orders": [{ "order_id": "o1", "order_amount": 100.50 },{ "order_id": "o2", "order_amount": 200.75 }]}POST users/_doc{"user_id": "u2","user_name": "Bob","orders": [{"order_id": "o3","order_amount": 50.25}]}
2. 查询示例
查询订单金额大于 100 的记录:
GET users/_search{"query": {"nested": {"path": "orders","query": {"range": {"orders.order_amount": {"gte": 100}}}}}}
3. 特点与注意事项
优点:数据存储在单一文档中,查询性能较高,适合一对多关系。
缺点:更新嵌套字段需要重写整个文档,数据量大时可能增加开销。
适用场景:数据关系稳定,更新频率较低。
方法三:使用父子关系
1. 索引设计
在同一索引中使用 join 字段定义父子关系:
PUT users_orders{"mappings": {"properties": {"my_join_field": {"type": "join","relations": {"user": "order"}},"user_id": {"type": "keyword"},"user_name": {"type": "text"},"order_id": {"type": "keyword"},"order_amount": {"type": "float"}}}}
插入父文档(user)
POST users_orders/_doc/u1?routing=u1{"user_id": "u1","user_name": "Alice","my_join_field": "user"}
插入子文档(order)
POST users_orders/_doc/o1?routing=u1{"order_id": "o1","user_id": "u1","order_amount": 100.50,"my_join_field": {"name": "order","parent": "u1"}}
2. 查询示例
查询有订单金额大于 100 的用户的记录:
GET users_orders/_search{"query": {"has_child": {"type": "order","query": {"range": {"order_amount": {"gte": 100}}}}}}
3. 特点与注意事项
优点:支持动态添加子文档,适合数据频繁更新的场景。
缺点:查询性能较嵌套文档低,分片路由需额外管理。
适用场景:需要灵活维护一对多关系的场景。
对比与选择建议

注意事项
1.性能优化:
大规模数据场景下,优先考虑嵌套文档或预聚合数据,避免频繁跨索引关联。
使用 LOOKUP JOIN 时,测试查询性能,确保索引规模可控。
2.版本要求:
LOOKUP JOIN 需 Elasticsearch 8.18 或更高版本。
关于公司
感谢您关注新智锦绣科技(北京)有限公司!作为 Elastic 的 Elite 合作伙伴及 EnterpriseDB 在国内的唯一代理和服务合作伙伴,我们始终致力于技术创新和优质服务,帮助企业客户实现数据平台的高效构建与智能化管理。无论您是关注 Elastic 生态系统,还是需要 EnterpriseDB 的支持,我们都将为您提供专业的技术支持和量身定制的解决方案。
欢迎关注我们,获取更多技术资讯和数字化转型方案,共创美好未来!
![]() | ![]() |
Elastic 微信群 | EDB 微信群 |

发现“分享”和“赞”了吗,戳我看看吧






