注:ElasticSearch
版本爲5.4
。html
在咱們的日誌系統裏須要一些系統索引,這些系統索引在應用初始化的時候就會被添加到ElasticSearch
中去,這些在ElasticSearch
中的系統索引在沒有索引數據的時候,只有索引名和一些配置信息,沒有mapping
信息。當用戶去根據時間區間排序搜索日誌信息的時候,ElasticSearch
就會產生all shards failed
異常。具體異常信息以下:java
Caused by: [.alert/NXa3zq5WSb-wGBKgyZibzw] QueryShardException[No mapping found for [timestamp] in order to sort on] at org.ElasticSearch.search.sort.FieldSortBuilder.build(FieldSortBuilder.java:262) at org.ElasticSearch.search.sort.SortBuilder.buildSort(SortBuilder.java:156) at org.ElasticSearch.search.SearchService.parseSource(SearchService.java:617) at org.ElasticSearch.search.SearchService.createContext(SearchService.java:468) at org.ElasticSearch.search.SearchService.createAndPutContext(SearchService.java:444) at org.ElasticSearch.search.SearchService.executeQueryPhase(SearchService.java:252) at org.ElasticSearch.action.search.SearchTransportService$6.messageReceived(SearchTransportService.java:331) at org.ElasticSearch.action.search.SearchTransportService$6.messageReceived(SearchTransportService.java:328) at org.ElasticSearch.transport.RequestHandlerRegistry.processMessageReceived(RequestHandlerRegistry.java:69) at org.ElasticSearch.transport.TransportService$7.doRun(TransportService.java:627) at org.ElasticSearch.common.util.concurrent.ThreadContext$ContextPreservingAbstractRunnable.doRun(ThreadContext.java:638) at org.ElasticSearch.common.util.concurrent.AbstractRunnable.run(AbstractRunnable.java:37) ... 3 more
查看了.alert
的索引數據再結合ElasticSearch
的異常信息判斷,我懷疑是因爲.alert
系統索引沒有timestamp mapping
信息引發的,.alert
索引初始化沒有任何數據時,ElasticSearch
中的信息以下:api
http://dev:9200/.alert
{ ".alert": { "aliases": { "alert": {} }, "mappings": { "alert": {} }, "settings": { "index": { "refresh_interval": "-1", "number_of_shards": "5", "provided_name": ".alert", "creation_date": "1533613744728", "store": { "type": "fs" }, "number_of_replicas": "1", "uuid": "YuPjsObOTMO6u3fEdG6hVw", "version": { "created": "5040099" } } } } }
看到這些信息以後,我開始了用如下方法嘗試解決。服務器
如下方法1和方法2都以失敗而了結,只有方法3能夠成功解決該問題。但在解決問題中我查找了不少資料,讓我對ElasticSearch
的mapping
有了更深地理解,所以我將解決該問題的過程記錄了下來。app
首先,因爲是沒有timestamp
這個mapping
信息,所以我想到建立索引模板,將.alert
這個索引的mappings
信息用模板來設置,以便在索引建立的時候就有相應的mapping
信息。模板信息以下:ide
{ "alert": { "order": 0, "template": "alert", "settings": { "index": { "number_of_shards": "5", "number_of_replicas": "1", "refresh_interval": "2s" } }, "mappings": { "alert": { "properties": { "timestamp": { "type": "date" } } } }, "aliases": {} } }
可是,通過測試後發現,all shards failed
的問題仍是會產生。究其緣由是因爲:測試
索引模板只會在插入新索引數據的時候生效,若是沒有索引數據,索引模板定義的
mappings
信息不會生效,並且對模板的改變不會影響到已存在的索引。大數據
此時,.alert
這個索引爲空,尚未新數據插入,所以,模板不會生效,也就導致該方法不會解決all shards failed
的問題。ui
因爲ElasticSearch
容許在建立索引時就建立mapping
信息,因而我想到了這個方法,通過測試後,能夠解決all shards failed
的問題。可是,產生了一個嚴重的後果,咱們用.alert
索引來記錄服務器報警信息,當我往.alert
這個索引裏添加數據時,只有timestamp
這個字段的數據添加進去了,其餘數據像產生報警的主機、報警內容等信息添加失敗。日誌
查詢官方文檔發現:
mapping
信息一旦被建立,就不容許被修改。改變已有的mapping
就意味着使已經存在的索引數據無效,解決的辦法就是使用正確的mappings
信息來建立新的索引,而後從新把數據添加到新索引中。雖然官方提供了reindex
方法來解決這個問題,可是,在大數據量的狀況下,reindex
代價比較高,所以,建立索引時添加mapping
這個方法也行不通。
ElasticSearch
的search api
能夠設置排序時忽略字段的哪些映射。默認狀況下,若是沒有與排序字段關聯的映射,則搜索請求將失敗。unmapped_type
選項容許設置忽略沒有映射的字段,從而不對該字段排序。因爲timestamp
的mapping
爲date
類型,所以,在搜索排序條件中增長{"timestamp":{"unmapped_type":"date"}}
成功解決因爲排序字段沒有date
映射引發的all shards failed
問題。
索引模板官方文檔:Index Templates
索引排序官方文檔:Sort
更新已存在的mapping
信息官方文檔:updating_existing_mappings
stackoverflow
問題連接:No mapping found for field in order to sort on in ElasticSearch