Elasticsearch 父子關系


 Elasticsearch的父子關系在一定場景下非常有利於我們進行關聯查詢,合理使用能加快我們的索引速度。

父子關系圖

對於Elasticsearch的 Parent and Child:

  1. 家庭關系:

 

 

2.學校關系:

 

 

3.等等關系我們都可以用父子關系來表示,這非常有利於我們進行父子關系的查詢。

Parent and Child 有如下特點:
  • 父子關系

  • 每個父母有多個孩子

  • 多個層次的親子關系

這里我們使用汽車關系來進行相關展示:

 

 

 

 

創建相關索引

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可能是管理關系的一種不錯選擇,但代價是很高的。必須意識到這種權衡,例如父子文檔的物理存儲約束和增加的復雜性。另一個預防措施是避免多層父子關系,因為這將消耗更多的內存和計算量。這些都是我們在使用父子關系的時候必須要考慮到的相關內容,避免造成不必要的損失。二哈覺得大家還是要根據實際場景來選擇合適自己的,綜合考慮自己的需求,沒有什么是一套全通的呀!ღゝ◡╹)ノ♡

二哈最近開通了公眾號呀,在這里你可以收獲最新的資訊呀,千萬別錯過啦!

歡迎兄弟們關注關注。

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM