Elasticsearch的父子關係在一定場景下非常有利於我們進行關聯查詢,合理使用能加快我們的索引速度。
父子關係圖
對於Elasticsearch的 Parent and Child:
-
家庭關係:
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可能是管理關係的一種不錯選擇,但代價是很高的。必須意識到這種權衡,例如父子文件的物理儲存約束和增加的複雜性。另一個預防措施是避免多層父子關係,因為這將消耗更多的記憶體和計算量。這些都是我們在使用父子關係的時候必須要考慮到的相關內容,避免造成不必要的損失。二哈覺得大家還是要根據實際場景來選擇合適自己的,綜合考慮自己的需求,沒有什麼是一套全通的呀!ღゝ◡╹)ノ♡
二哈最近開通了公眾號呀,在這裡你可以收穫最新的資訊呀,千萬別錯過啦!
歡迎兄弟們關注關注。