Elasticsearch 有沒有陣列型別?有哪些坑?
1、Elasticsearch 陣列常見問題清單
近期 Elasticsearch 陣列問題被問到的比較多,為了方便大家對陣列建立全域性認知, 我把陣列相關實戰問題梳理出來,讓更多後來人遇到類似問題少走不必要的彎路。
精簡幾個核心問題列舉如下:
-
Elasticsearch 是否有陣列型別?
-
Elasticsearch 資料選型有沒有坑?
-
Elasticsearch 如何獲取陣列中第i號位置的值?
-
Elasticsearch 如何獲取陣列最後一個元素的值?
2、Elasticsearch 是否有陣列型別?
瞭解 Elasticsearch 版本歷史的讀者會知道 1.X 版本中沒有獨立模組強調陣列 Array 型別。
Elasticsearch 2.X 版本之後,陣列型別才單獨被拎出來。
在 Elasticsearch 中,沒有專門的陣列資料型別。預設情況下,任何欄位都可以包含零個或多個值,但是,陣列中的所有值必須具有 相同的 資料型別。什麼意思呢?
-
long 型別儲存一個值是long型別,儲存多個自然就成為 long 陣列型別;
-
keyword 型別儲存一個值是 keyword 型別,儲存多個值就成為 keyword 陣列型別。
實戰一把:
PUT my-index-1230 { "mappings": { "properties": { "horry": { "type": "keyword" } } } } # 單值 keyword 型別 POST my-index-1230/_doc { "horry": "pingpang" } # keyword 陣列型別 POST my-index-1230/_doc { "horry": [ "pingpang", "basketball", "football" ] } GET my-index-1230/_search
如上示例,可以更加清晰的看出,當我們選型使用陣列時,和平時 Mapping 設定型別一樣,不需要額外的修改 Mapping 任何內容,只需要匯入相同資料型別的資料即可。
這時候,讀者可能會問,我不小心寫入了不同型別的資料咋辦?
繼續實戰一把,探個究竟。
# 匯入不合規資料,資料依然可以寫入 POST my-index-1230/_doc {"horry":["11111",22222,33333]} # 資料依然可以被召回 GET my-index-1230/_search { "query": { "term": { "horry": { "value": "22222" } } } }
由於 Elasticsearch 做了弱型別匹配校驗檢查,導致資料依然可以寫入,我們肉眼看到的整形型別,實際本質儲存為keyword 型別,這也是為什麼“22222”能被檢索召回的原因。
3、Elasticsearch 資料選型有沒有坑?
3.1 動態匯入陣列型別資料,第一次寫入資料的型別決定了陣列的型別。
# 預設檢測指定為 long 型別 POST my-index-1230-01/_doc { "horry": [ 11111, 22222, 33333 ] }
如上,寫入的是 long 型別的陣列。long 咋來的,動態型別匹配 date_detection 得到的!
http://www.elastic.co/guide/en/elasticsearch/reference/current/dynamic-mapping.html
3.2 不能獨立的檢索陣列中的單個欄位
如下示例,即便僅檢索“basketball”不能獨立只召回“basketball”,陣列資料會一起返回。
# 陣列資料會作為一個整體被召回 GET my-index-1230/_search { "query": { "match": { "horry": "basketball" } } }
如果非要實現單獨召回資料,需要藉助:nested 巢狀型別實現。
4、Elasticsearch 如何獲取陣列中第i號位置的值?
舉例,僅檢索召回 “basketball”,需要藉助 script_field 或者 runtime field 實現。
實現參考如下:
POST my-index-1230/_doc { "horry": [ "all", "pingpang", "basketball", "football" ] } GET my-index-1230/_search
注意:儲存陣列資料順序是:
序號 | 值 |
---|---|
0 | all |
1 | pingpang |
2 | basketball |
3 | football |
GET my-index-1203/_search { "query": { "match_all": {} }, "script_fields": { "test1": { "script": { "lang": "painless", "source": "doc['horry'][2]" } } } }
如上示例中的2,可以換成:0,1,2,3。
召回結果
如下:
序號 | 值 |
---|---|
0 | all |
1 | basketball |
2 | football |
3 | pingpang |
後臺按照字母順序做了處理,返回結果資料。
也就是說:我們以指令碼的方式 無法精準獲取對應位次上的資料 。
這塊目前看,沒有最優的獲取方式。如果大家有,歡迎留言交流。
4、Elasticsearch 如何獲取陣列最後一個元素的值?
通過 ingest pipeline 預處理方式實現如下:
DELETE my-index-123001 POST my-index-123001/_doc { "horry": [ "pingpang", "basketball", "football" ] } PUT _ingest/pipeline/my_pipeline { "processors": [ { "script": { "source": """ if(ctx.horry!=null) { List list = ctx.horry; List ListOfLast = list.subList(list.size() - 1, list.size()); String lastval=ListOfLast.toString(); lastval=lastval.substring(1, lastval.length() - 1); ctx.lastval=lastval; } """ } } ] } POST my-index-123001/_update_by_query?pipeline=my_pipeline { "query": { "match_all": {} } } GET my-index-123001/_search
中間核心指令碼不是最優實現方式,歡迎大家留言反饋精簡處理方式。
-
第一步:陣列轉 list;
-
第二步:取 list 最後一個元素值,結果仍然為 list;
-
第三步:list 轉 string;
-
第四步:string 取核心元素,去頭、去尾。
-
第五步:將中間結果賦值給新欄位。
返回結果如下:
{ "_index" : "my-index-123001", "_type" : "_doc", "_id" : "RxLlC34BuPkjCUZU5-XW", "_score" : 1.0, "_source" : { "lastval" : "football", "horry" : [ "pingpang", "basketball", "football" ] } }
上面的預處理方式對陣列而言,也是僅適用於獲取特定值的場景。
5、小結
Elasticsearch 陣列選型需要結合業務場景需要。
資料相關的問題還有很多很多,比如:
-
陣列高亮問題
-
陣列聚合問題
-
陣列召回資料問題
-
.....
大家在選型或者實踐的過程中,如果涉及大量指令碼的時候,要多考慮能否通過寫入前 ingest 預處理方式。本質是:以空間換時間,最大化提升檢索效率。
歡迎大家就陣列問題留言討論。
更 短時間 更 快習得 更 多幹貨!
已帶領 81 位 球友 通過 Elastic 官方認證!
比同事 搶先 一步學習進階乾貨 !
- 乾貨 | Elasticsearch 8.X 節點角色劃分深入詳解
- Elasticsearch 快照生命週期管理 (SLM) 實戰指南
- 乾貨 | Elasticsearch 資料建模指南
- 運用 Elasticsearch 8.1.x 實現智慧問答系統
- 乾貨 | Elasticsearch 檢索型別選型指南
- 從一個線上問題看 Elasticsearch 資料清洗方式
- 用 Elasticsearch 統計做了幾次核酸檢測?怎麼破?
- 看著非常炫酷的Kibana視覺化,你也可以搞定!
- Elasticsearch 叢集狀態變成黃色或者紅色,怎麼辦?
- 動手體驗ES8.1.x實時監控Java應用執行狀態
- 乾貨 | Elasticsearch Nested 陣列大小求解,一網打盡!
- Elasticsearch 出現 “429 rejected” 報錯,怎麼辦?
- 阿里雲大佬叮囑我務必要科普這個 Elasticsearch API
- Elasticsearch JVM 堆記憶體使用率飆升,怎麼辦?
- esrally 如何進行簡單的自定義效能測試?
- Elasticsearch 斷路器報錯了,怎麼辦?
- MetricBeat Elasticsearch Kibana 實現監控指標視覺化
- Elasitcsearch CPU 使用率突然飆升,怎麼辦?
- Elasticsearch 磁碟使用率超過警戒水位線,怎麼辦?
- 5年 Elasticsearch 電商實戰經驗深度覆盤