发布时间:2025-06-24 19:50:31 作者:北方职教升学中心 阅读量:227
一、
POSTorder-join/_search{"aggs":{"goods":{"terms":{"field":"goods_name","size":10},"aggs":{"goods_data":{"parent":{"type":"goods"},"aggs":{"orders":{"terms":{"field":"buyer","size":10}}}}}}}}
发布时间:2025-06-24 19:50:31 作者:北方职教升学中心 阅读量:227
POSTorder-join/_search{"aggs":{"goods":{"terms":{"field":"goods_name","size":10},"aggs":{"goods_data":{"parent":{"type":"goods"},"aggs":{"orders":{"terms":{"field":"buyer","size":10}}}}}}}}
在Elasticsearch中,父子索引类型join是通过特殊的字段类型来实现的,该字段类型被称为“join”。使用对象数组存在的问题
对象数组的默认存储方式:
Elasticsearch内部并不直接支持对象的层次结构,而是将对象层次结构扁平化为一个字段名和字段值的简单列表。
Nested类型:
在底层,Elasticsearch使用特殊的路由机制来确保父子文档存储在同一个分片上。
父子类型:
数据聚合和分析:在数据分析场景下,我们可能需要对具有层级关系的数据进行聚合操作。这个字段允许我们定义文档之间的父子关系。在这篇博客中,我们将深入探讨Elasticsearch中的父子索引类型join,包括其工作原理、例如,我们可以统计每个买家购买的商品名称和数量。
数据层级关系的表示:在实际应用中,很多数据天然具有层级或关联关系。
POSTorder-join/_search{"query":{"has_child":{"type":"goods","query":{"match_all":{}}}}}
父文档主键搜索:通过父文档的主键值来查询所有关联的子文档。这是非常重要的,因为这样可以提高查询性能并确保数据的一致性。通过使用父子索引类型,Elasticsearch可以高效地处理这类关联查询,因为它内部优化了父子文档之间的关联访问。
虽然父子索引类型提供了解决上述问题的有效手段,但它也带来了一些额外的复杂性和性能考虑。例如,一个博客系统可能包含博客文章和对应的评论,其中博客文章是父级数据,而评论是与文章相关联的子级数据。
POSTorder-join/_search{"query":{"parent_id":{"type":"goods","id":"1"}}}
join字段还支持children和parent聚集操作,用于对父子文档进行统计分析。通过使用父子关系,可以更容易地管理和维护这种完整性。这种处理方式可能导致数据关联性的丢失。
join字段提供了一种在索引中明确定义父子文档之间关系的方法。父子索引类型join的工作原理和作用
Elasticsearch是一个强大的搜索引擎,它提供了丰富的功能来满足复杂的搜索需求。
- 查询性能:查询性能可能略低于Nested类型,因为父子文档是分开存储的,查询时可能需要进行额外的连接操作。这是因为Lucene(Elasticsearch的底层库)没有内部对象的概念,它将内部对象扁平化处理了。
POSTorder-join/_search{"query":{"has_parent":{"parent_type":"order","query":{"term":{"buyer":{"value":"tom"}}}}}}
以子搜父:通过子文档的属性来查询父文档。以子搜父等特殊搜索方式,使得查询更加灵活和高效。在内部,文档实际上被存储为:
{"group":"man","userName.first":["张","李"],"userName.last":["三","四"]}
可以看到,
userName.first
和userName.last
被扁平化为多值字段,它们之间的关联性已经丢失,因此查询结果可能不符合我们的预期。二、通过将相关联的数据组织在同一个索引中,并明确它们的层级关系,可以减少数据冗余和提高数据的一致性。父子join关联的使用
- 3.1 创建带join字段的索引
- 3.2 添加父子文档
- 3.3 特殊搜索方式
- 3.4 聚集操作
- 四、比如,我们可能想要找到所有包含特定评论的博客文章,或者查找某篇博客文章下的所有评论。
在Elasticsearch的实际应用中,嵌套文档是一个常见的需求,尤其是当我们需要对对象数组进行独立索引和查询时。应用层关联数据
除了使用join字段,还可以在应用层通过外键字段来实现父子关联。
Elasticsearch中的父子索引类型join是一个强大的工具,它允许我们在同一索引中创建具有层级关系的文档。例如,我们可以查询订单号为1的所有商品。例如,我们可以定义一个订单索引,其中包含商品子文档。
PUTorder-join/_doc/1{"orderid":"1","buyer":"tom","order_time":"2020-11-04 00:00:00","my_join_field":{"name":"order"}}PUTorder-join/_doc/2?routing=1{"goodsid":"1","goods_name":"milk","price":5.2,"produce_time":"2020-10-04 00:00:00","my_join_field":{"name":"goods","parent":"1"}}
利用join字段,可以实现一些特殊的搜索操作:
以父搜子:通过父文档的属性来查询子文档。然而,使用以下查询:
GET/user/user_info/_search{"query":{"bool":{"must":[{"match":{"userName.first":"张"}},{"match":{"userName.last":"四"}}]}}}
意外地,我们可能会得到结果。
文档间的引用完整性:在某些情况下,确保文档间的引用完整性是很重要的。在Elasticsearch中,这类嵌套结构被称为父子文档,它们能够“彼此独立地进行查询”。例如,考虑以下文档:
PUTuser/user_info/1{"group":"man","userName":[{"first":"张","last":"三"},{"first":"李","last":"四"}]}
如果我们尝试查询first
为“张”且last
为“四”的数据,按照常理,这样的数据应该不存在。
关联查询的优化:当数据之间存在关联关系时,我们经常需要进行跨层级的查询。然而,在使用时需要注意性能影响和数据一致性等问题,并确保与当前Elasticsearch版本的兼容性。每个文档都是单独存储的,但它们之间通过特定的join字段来建立关联。例如,我们可以查询所有属于特定买家的商品。因此,在设计数据模型时需要谨慎考虑父子关系的使用。在映射中加入join字段,并设置好父子关系的名称。Nested类型更适合处理静态的、
Nested类型和父子Join类型在处理关联数据时各有优势。例如,我们可以查询所有包含特定商品的订单。当我们索引一个子文档时,需要使用routing参数来指定其父文档的ID,以便Elasticsearch可以将它们路由到相同的分片。这些对象在内部被视为独立的文档,可以独立地进行索引和查询。当数据量非常大时,单个分片上的文档数量可能会增加,从而影响查询和索引性能。实现这一功能主要有两种方式:
创建一个新的索引,并定义好父子文档的映射关系。
PUTorder-join{"settings":{"number_of_shards":5,"number_of_replicas":1},"mappings":{"properties":{"orderid":{"type":"integer"},"buyer":{"type":"keyword"},"order_time":{"type":"date","format":"yyyy-MM-dd HH:mm:ss"},"goodsid":{"type":"integer"},"goods_name":{"type":"keyword"},"price":{"type":"double"},"produce_time":{"type":"date","format":"yyyy-MM-dd HH:mm:ss"},"my_join_field":{"type":"join","relations":{"order":"goods"}}}}}
在添加文档时,需要明确指定文档的父子关系。删除和修改操作,而不需要对整个数组进行操作。通过正确使用join字段和相关的查询DSL,我们可以有效地表示和查询具有父子关系的数据模型。
children聚集:统计每个父文档的子文档数据。
POSTorder-join/_search{"query":{"match_all":{}},"aggs":{"orders":{"terms":{"field":"buyer","size":10},"aggs":{"goods_data":{"children":{"type":"goods"},"aggs":{"goods_name":{"terms":{"field":"goods_name","size":10}}}}}}}}
parent聚集:统计每个子文档的父文档数据。
简化数据模型:在某些情况下,使用父子关系可以简化数据模型的设计。使用join字段的优势在于: