當前位置:
首頁 > 知識 > ElasticSearch裡面一些小坑筆記

ElasticSearch裡面一些小坑筆記

最近線上的es報了一個異常,核心信息如下:


No mapping found for [k1.k2.time] in order to sort on

我們的es索引是嵌套索引,上面的這個異常大致意思是說在某個shard裡面嵌套結構裡面

k1.k2.time這個欄位不存在數據,所以排序失敗。

我們知道在ES裡面可以分shard和索引,大多數時候我們es索引都是自動按某個規則創建的,比如說按天,按月,按年,這個用過logstash的同學應該都比較熟悉,收集的log基本上都是按天生成索引的,然後我們用kibana查詢或者自己寫代碼查詢。

下面看一些問題場景:

(場景1)查詢一個不存在的索引

默認情況下,查詢一個不存在的索引是會報異常的(no such index....)

,那麼如何避免這個問題呢?

有兩種辦法:

A:每次查詢前去使用es的索引api判斷這個索引存在不存在,如果不存在就不進行任何操作,存在的話在執行查詢,這樣就能避免,但這樣的問題就是每次都得判斷存在不存在多一次查詢交互。

B:在構建查詢時,使用通配符標識索引,如果這個索引不存在,查詢結果就是空,但是不會報異常,這樣比較方便,不需要關注存在不存在問題。

一個java api的例子如下:

SearchRequestBuilder search = client.prepareSearch("xxxxx2019-06-13*").setTypes("xxxx")

如上代碼,查詢這個不存在的索引,這段代碼結果不會報錯,推薦使用這種方法。

(場景2)查詢一個不存在的欄位

查詢一個不存在的欄位es是不會報錯的

(場景3)排序一個不存在的欄位

默認情況下,排序一個不存在的欄位,在es裡面也會報錯。這裡主要分三種情況:

A:排序的單個索引不存在這個欄位

B:排序的單個索引存在這個欄位,但是它分shard了,如果有3個shard,只有2個shard上有這個欄位,另外一個shard上沒有這個欄位,那麼它同樣會報異常

C:跨索引查詢,如果跨2個索引,一個索引上所有的shard都包含這個欄位,另外一個索引有部分shard沒有,那麼也會出現這個問題

如何解決:

這個也比較好解決,在排序的時候,需要設置在maping裡面不存在的裡面,應該如何處理,容錯代碼如下:

search.addSort(SortBuilders.fieldSort("no_exists_field").unmappedType("integer").order(SortOrder.DESC))

注意unmappedType方法了,定義這個值不存在的時候,默認按什麼類型處理。

(場景4)在一個不存在的欄位上算count,max,min,sum,avg這些指標

求聚合統計這些指標時,也不會報錯,但結果值列有不同,詳情如下:

count:0
sum:0.0
max:-Infinity
min:Infinity
avg:NaN

(場景5)分組一個不存在的欄位

分組一個不存在的欄位,也不會報錯,返回結果是空

上面這些場景基本涵蓋了查詢統計大多數的可能出現的問題,需要我們在使用的時候需要注意一下,避免一些不必要的問題。

最後我們來介紹一下es裡面一個有用的查詢Exists Query:

功能:查詢的欄位至少有一個非null值才回返回

我們來看官網給的一個例子:

{
"exists" : { "field" : "user" }
}

上面這個查詢是查欄位user的數據,是不是為空,注意下面的這些數據,是可以被匹配上

{ "user": "jane" } //有數據
{ "user": "" } //空串也代表有數據
{ "user": "-" } //符號也代表有數據
{ "user": ["jane"] }//數組也代表有數據
{ "user": ["jane", null ] } //數組裡面有一個不是null也代表有數據

在來看下,那些情況,不能被匹配:

{ "user": null }//null值不能被匹配
{ "user": } //空數組不能被匹配
{ "user": [null] } //空數組包含null值也不能被匹配
{ "foo": "bar" } //user欄位缺失,也不能被匹配

此外,Exists Query可以非常方便的替代Miss Query看下面的例子:

"bool": {
"must_not": {
"exists": {
"field": "user"
}
}
}

上面這個查詢將返回沒有user欄位的數據,java api寫法如下:

BoolQueryBuilder boolQuery = QueryBuilders.boolQuery;
boolQuery.mustNot(QueryBuilders.existsQuery("user"));

注意,經過測試發現一個嵌套索引裡面,如果只有一個為空的數組,然後使用嵌套查詢Exists Query是會報錯的,而使用平鋪的Exists Query是不會報錯的,也就是說,嵌套的索引裡面必須有一個不為空的對象存在,才能使用Exists Query查詢語法,來查詢相關欄位不存在的數據

否則會報錯,這一點目前還沒看到有任何好的辦法來校驗多級嵌套結構下的某個索引裡面到底存不存在某個嵌套結構,嵌套索引的判斷是否存在大致一樣

唯一需要注意到是,嵌套結構,一定有一條不為空的數據存在才行

喜歡這篇文章嗎?立刻分享出去讓更多人知道吧!

本站內容充實豐富,博大精深,小編精選每日熱門資訊,隨時更新,點擊「搶先收到最新資訊」瀏覽吧!


請您繼續閱讀更多來自 達人科技 的精彩文章:

EF Core學習Code First
多線程和非同步編程示例和實踐-踩過的坑
Java類的載入的一個小問題
cordova 插件開發

TAG:達人科技 |

您可能感興趣

The Economist 精讀筆記:Catching the bitcoin bug
論文筆記:Sequence Generative Adversarial Nets with Policy Gradient
【Code筆記本】Valid Parentheses
讀書筆記:Eating for Cognitive Power
Machine Learning Yearning 要點筆記
《Relation Networks for Object Detection》論文筆記
筆記應用GoodNotes將推出macOS版本,基於Project Catalyst框架
Spring Cloud Feign使用筆記
handlebars筆記總結
Ahmedabad,India攝影筆記
論文筆記:Fraternal Dropout
帶著小小筆記本,隨時隨地high起來 / Yacine Ait Kaci
微軟Surface Laptop筆記本新增Core m3款
論文筆記:Attention is All You Need
Gartner:微軟Surface可以叫筆記本,iPa d不行
Gartner:微軟Surface可以叫筆記本,iPad不行
【咖啡筆記】Viennese&Mocha
Spring Cloud斷路器Hystrix原理讀書筆記
Surface Phone將支持「筆記本模式」
微軟機器學習Machine Learning Studio學習筆記