Elasticsearch的父子关系在必定场景下很是有利于咱们进行关联查询,合理使用能加快咱们的索引速度。javascript
对于Elasticsearch的 Parent and Child:java
家庭关系:app
2.学校关系:ide
3.等等关系咱们均可以用父子关系来表示,这很是有利于咱们进行父子关系的查询。性能
父子关系flex
每一个父母有多个孩子spa
多个层次的亲子关系code
这里咱们使用汽车关系来进行相关展现:blog
PUT family_tree{ "settings": { "index":{ "number_of_shards":1, "number_of_replicas":0 } }, "mappings": { "properties": { "name":{ "type": "text" }, "price":{ "type": "text" }, "isSale":{ "type": "boolean" }, "relation_type":{ "type": "join", "eager_global_ordinals": true, "relations":{ "parent":"child" } } } }}
注意:父子关系中使用 "eager_global_ordinals"
能加速join
.索引
因为存储的数据已被非规范化。所以联接不能跨索引,子文档和父文档必须位于相同的索引和相同的分片中。父子关系须要在统一分片中:经过固定值来路由(routing)到同一个分片中。
分片规则:shard = hash(routing_value) % number_of_primary_shards
PUT family_tree/_doc/1?routing=Car{ "name":"Car", "price":"2000000", "isSale":true, "relation_type":{ "name":"parent" }}
PUT family_tree/_doc/2?routing=Car{ "name":"Van", "price":"10000", "isSale":true, "relation_type":{ "name":"child", "parent":1 }}
PUT family_tree/_doc/3?routing=Car{ "name":"Sedan", "price":"10000", "isSale":true, "relation_type":{ "name":"child", "parent":1 }}
PUT family_tree/_doc/4?routing=Car{ "name":"SUV", "price":"8000", "isSale":true, "relation_type":{ "name":"child", "parent":1 }}
注意:子文档和父文档必须位于同一分片上的限制。
获取Car的全部子级:parent_id查询可用于查找属于特定父级的子级文档。
GET /family_tree/_search?pretty=true{ "query": { "parent_id":{ "type":"child", "id":"1" } }}
结果:以查找出属于parent_id
为 1 的全部子级文档。
在这以前咱们先为 Car 添加一个再也不销售的汽车类型:
PUT family_tree/_doc/5?routing=Car{ "name":"Sports car", "price":"30000000", "isSale":false, "relation_type":{ "name":"child", "parent":1 }}
1.用bool与must结合获取全部未售 Car 的孩子:
GET /family_tree/_search{ "query": { "bool": { "filter": { "term": { "isSale": "false" } }, "must": [ { "parent_id":{ "type":"child", "id":"1" } } ] } }}
结果:从查询到的结果中能够看到:只有"Sports car"符合咱们查询的条件。
2.咱们也能够经过has_child
查询拥有子节点未销售状态的父节点信息:
GET /family_tree/_search?pretty{ "query": { "has_child": { "type": "child", "query": { "bool": { "must": [ {"match": {"isSale": "false"}} ] } } } }}
3.has_parent关键字可帮助咱们获取全部有父母且符合过滤条件的孩子信息。经过has_parent来查询父节点状态为在售的全部子节点信息:
GET /family_tree/_search?pretty{ "query": { "has_parent": { "parent_type": "parent", "query": { "match": { "isSale": "true" } } } }}
每一个关系级别都会在查询时增长内存和计算方面的开销,不建议使用多个级别的关系模型。
本次收获:
父子文档必须索引到同一个分片中。
每一个索引仅容许一个链接字段映射。
一个元素能够有多个子级,但只能有一个父级。
能够向已存在的联接字段添加新关系。
也能够将子元素添加到现有元素中,但前提是该元素已是父元素。
当索引时间性能比搜索时间性能更重要时,父子join多是管理关系的一种不错选择,但代价是很高的。必须意识到这种权衡,例如父子文档的物理存储约束和增长的复杂性。另外一个预防措施是避免多层父子关系,由于这将消耗更多的内存和计算量。这些都是咱们在使用父子关系的时候必需要考虑到的相关内容,避免形成没必要要的损失。二哈以为你们仍是要根据实际场景来选择合适本身的,综合考虑本身的需求,没有什么是一套全通的呀!ღゝ◡╹)ノ♡
二哈最近开通了公众号呀,在这里你能够收获最新的资讯呀,千万别错过啦!
欢迎兄弟们关注关注。