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多是管理關係的一種不錯選擇,但代價是很高的。必須意識到這種權衡,例如父子文檔的物理存儲約束和增長的複雜性。另外一個預防措施是避免多層父子關係,由於這將消耗更多的內存和計算量。這些都是咱們在使用父子關係的時候必需要考慮到的相關內容,避免形成沒必要要的損失。二哈以爲你們仍是要根據實際場景來選擇合適本身的,綜合考慮本身的需求,沒有什麼是一套全通的呀!ღゝ◡╹)ノ♡
二哈最近開通了公衆號呀,在這裏你能夠收穫最新的資訊呀,千萬別錯過啦!
歡迎兄弟們關注關注。