Elasticsearch Join字段類型簡單快速上手教程
閱讀本文需要一定的Elasticsearch
基礎(chǔ)哦,本文深度有,但是不深
概述
Elasticsearch中Join
數(shù)據(jù)類型的字段相信大家也都用過,也就是口中常談的父子文檔。在Elasticsearch中Join
不能跨索引和分片,所以保存文檔信息時要保證父子文檔使用相同的路由參數(shù)來保證父文檔與子文檔保存在同一個索引的同一個分片,那么都有哪些限制呢?
父子關(guān)系的限制
- 每個索引中只能有一個關(guān)系字段
- 父文檔與子文檔必須在同一個索引分片中,所以我們在對父子文檔增加、刪除、修改時要設(shè)置路由值,保證數(shù)據(jù)都在同一分片
- 一個父文檔可以包含多個子文檔,但是一個子文檔只能有一個父文檔
- 只能在
Join
類型的字段上建立關(guān)系 - 在保證當(dāng)前文檔是父文檔的前提下可以增加子文檔
Global ordinals
翻譯過來就是全局序數(shù)。什么是全局序數(shù)呢,官方文檔中說明了,這就是一個加速查詢的一個東西,使用了全局序數(shù)之后可以讓數(shù)據(jù)更緊湊;詳細(xì)的就不展開了,后面有機(jī)會再詳細(xì)說明一下全局序數(shù),具體的目前可以查看一下官方文檔
對于我們本章節(jié)內(nèi)容來說,我們知道父子文檔Join
類型是使用全局序數(shù)來加速查詢的就可以了。默認(rèn)情況下,全局序數(shù)基本是實(shí)時構(gòu)建的,當(dāng)索引發(fā)生變化,全局序數(shù)會重新構(gòu)建。這個過程會增加refresh
的時間,當(dāng)然這個配置也是可以關(guān)閉的,但是關(guān)閉之后會在我們接下來遇到的第一個父連接或者聚合的查詢時重新構(gòu)建全局序數(shù),這樣這一部分的時間就反饋給了用戶,官方也是不建議我們這樣做的,感覺對用戶來說不是那么的友好,主要還是在一個權(quán)衡。最壞的情況就是同時有多個寫入,也就是同時有多個全局序數(shù)需要重新構(gòu)建,也就會造成在單個refresh
的時間間隔內(nèi)要重新構(gòu)建多個全局序數(shù)
當(dāng)然如果關(guān)聯(lián)字段使用的不是很頻繁并且寫入事件很多,禁用掉是值得推薦的,禁用方式如下
PUT my-index-000001 { "mappings": { "properties": { "join_field": { "type": "join", "relations": { "goods": ["details","evaluate"], "evaluate":"vote" }, "eager_global_ordinals": false } } } }
當(dāng)然,對于全局序數(shù)占用的堆大小情況可以使用如下語句查看
# Per-index GET my-index-000001/_stats/fielddata?human&fields=join_field#goods # Per-node per-index GET _nodes/stats/indices/fielddata?human&fields=join_field#goods
父子文檔
首先我們還是創(chuàng)建一個正常的父子關(guān)系索引,商品作為父文檔,詳情作為子文檔
DELETE my-index-000001 PUT my-index-000001 { "mappings": { "properties": { "id": { "type": "keyword" }, "join_field": { "type": "join", "relations": { "goods": "details" } } } } }
- my-index-000001:索引名稱
- id:文檔主鍵
- join_field:父子關(guān)系字段,
type
標(biāo)記為Join
為父子文檔 - relations: 定義父子關(guān)系,
goods
為父文檔類型名稱,details
為子文檔類型名稱,后面插入數(shù)據(jù),查詢都會使用
插入幾條測試數(shù)據(jù),商品有iphon和mac,詳情為顏色外觀與內(nèi)存配置等
PUT my-index-000001/_doc/1?refresh { "id": "1", "text": "iphone 14 pro max", "join_field": { "name": "goods" } } PUT my-index-000001/_doc/2?refresh { "id": "2", "text": "macbook pro ", "join_field": { "name": "goods" } } PUT my-index-000001/_doc/3?routing=1&refresh { "id": "3", "text": "512G 16核", "join_field": { "name": "details", "parent": "1" } } PUT my-index-000001/_doc/4?routing=1&refresh { "id": "4", "text": "粉/銀/黑/抹茶綠", "join_field": { "name": "details", "parent": "1" } } PUT my-index-000001/_doc/5?routing=1&refresh { "id": "5", "text": "1T 32G", "join_field": { "name": "details", "parent": "2" } } PUT my-index-000001/_doc/6?routing=1&refresh { "id": "6", "text": "銀/黑", "join_field": { "name": "details", "parent": "2" } }
使用parent_id
查詢父子文檔,以上面插入的測試數(shù)據(jù)查詢,查找mac
的詳情信息語句如下,前提是知道父文檔的id
GET my-index-000001/_search { "query": { "parent_id": { "type": "details", "id":"2" } }, "sort":["id"] }
- 大部分情況上面是不能滿足我們的查詢請求的,所以我們還可以使用
has_parent
或者has_child
查詢
使用has_parent
查詢:父文檔goods
中所有包含macbook
的子文檔(后文的孫子文檔也可以查詢)
GET my-index-000001/_search { "query": { "has_parent": { "parent_type": "goods", "query": { "match": { "text": "macbook" } } } } }
使用hash_child
查看details
子文檔中有1T
關(guān)鍵字的所有父文檔
GET my-index-000001/_search { "query": { "has_child": { "type": "details", "query": { "match": { "text": "1T" } } } } }
使用parent-join
查詢或者聚合
Elasticsearch
在使用Join
類型數(shù)據(jù)類型時,會自動創(chuàng)建一個附加的字段,結(jié)構(gòu)為Join
的字段名加#號
加父類型,以上文為例,創(chuàng)建一個附加字段(join_field#goods
),如下是使用parent-join
字段查詢聚合的一個例子,參考自官網(wǎng),應(yīng)用了8.1版本
的新特性運(yùn)行時字段
GET my-index-000001/_search { "query": { "parent_id": { "type": "details", "id": "1" } }, "aggs": { "parents": { "terms": { "field": "join_field#goods", "size": 10 } } }, "runtime_mappings": { "my_parent_field": { "type": "long", "script": """ emit(Integer.parseInt(doc['join_field#goods'].value)) """ } }, "fields": [ { "field": "my_parent_field" } ] }
Join
類型的父子文檔,上面我們演示了一個父文檔對應(yīng)一種子文檔類型的例子,Join
類型也支持一個父類型有多個子類型,以上文為基礎(chǔ),加入下面語句測試
DELETE my-index-000001 PUT my-index-000001 { "mappings": { "properties": { "id": { "type": "keyword" }, "join_field": { "type": "join", "relations": { "goods": ["details","evaluate"] } } } } } PUT my-index-000001/_doc/7?routing=1&refresh { "id": "7", "text": "運(yùn)行流程,無卡頓,待機(jī)時間長", "join_field": { "name": "evaluate", "parent": "1" } } PUT my-index-000001/_doc/8?routing=1&refresh { "id": "8", "text": "體重輕,攜帶方便,編碼利器", "join_field": { "name": "evaluate", "parent": "2" } }
- 同樣的,細(xì)心的同學(xué)已經(jīng)看到了,上文已經(jīng)標(biāo)記了孫子文檔,對的,你沒看錯就是孫子文檔,三級的層級,級別可以更深,但是
Elasticsearch
不建議很深的層次,畢竟Join
很消耗性能的,層級再深點(diǎn)沒法用了,下面就是多級別的語句測試,此時他們?nèi)叩年P(guān)系就如下所示
DELETE my-index-000001 PUT my-index-000001 { "mappings": { "properties": { "id": { "type": "keyword" }, "join_field": { "type": "join", "relations": { "goods": ["details","evaluate"], "evaluate":"vote" } } } } } PUT my-index-000001/_doc/9?routing=1&refresh { "id": "9", "text": "這是投票信息:我買iphone是因?yàn)樾詢r比高,保值", "join_field": { "name": "vote", "parent": "1" } } PUT my-index-000001/_doc/10?routing=1&refresh { "id": "10", "text": "這是投票信息:我買mac是因?yàn)檩p,攜帶方便,沒有流氓軟件", "join_field": { "name": "vote", "parent": "2" } }
總結(jié)
相信大家也看出來了,官方都不建議使用父子文檔的,畢竟性能是一大問題,相信大家用Elasticsearch
肯定大部分都是圖速度快,用了Join
字段變慢了,這誰能同意呢是吧,有利有弊吧,看大家選擇,下一篇帶給大家的算是Elasticsearch
推薦Join
字段替代類型Nested
,更多關(guān)于Elasticsearch Join字段類型的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
jpa多條件查詢重寫Specification的toPredicate方法
這篇文章主要介紹了多條件查詢重寫Specification的toPredicate方法,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-11-11Spring?Boot深入排查?java.lang.ArrayStoreException異常
這篇文章介紹了Spring?Boot深入排查?java.lang.ArrayStoreException異常,文中通過示例代碼介紹的非常詳細(xì)。對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2021-12-12Java中為什么重寫equals()也需要重寫hashCode方法
這篇文章主要介紹了Java中為什么重寫equals()也需要重寫hashCode(),本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04關(guān)于SpringBoot靜態(tài)資源路徑管理問題
這篇文章主要介紹了SpringBoot靜態(tài)資源路徑管理,主要包括默認(rèn)靜態(tài)資源路徑,增加靜態(tài)資源路徑前綴的相關(guān)操作,本文給大家介紹的非常詳細(xì),需要的朋友可以參考下2022-05-05Java org.w3c.dom.Document 類方法引用報錯
這篇文章主要介紹了Java org.w3c.dom.Document 類方法引用報錯的解決方案,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2021-08-08如何在Java中獲取當(dāng)前年份(實(shí)例代碼)
在Java語言中獲取當(dāng)前年份有幾種方法:使用java.util包下的Calendar類,使用java.time包下的LocalDate類或者使用java.text包下的SimpleDateFormat類,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友參考下吧2023-11-11