注: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