背景
使用sort的时候需要注意,如果排序字段是字符串类型的(text、string),那么会按照排序字段的值的字典顺序进行排序。
而有时候我们需要按照实际数值进行排序,这时候就需要重建索引reindex,重建索引的时候使用新的模板或指定mapping,以便将排序字段的类型修改为integer之类的数值型。
步骤
1.新建模板
PUT _template/sort_template
{
"order": 1,
"index_patterns": "springboot*",
"settings": {
"number_of_shards": 5,
"number_of_replicas": 1
},
"mappings": {
"data":{
"dynamic_templates" : [ {
"keyword_field" : {
"match" : "*Name",
"match_mapping_type" : "string",
"mapping" : {
"type" : "text",
"fields": {
"raw": {
"type": "keyword"
}
}
}
}
}],
"properties": {
"execTime":
{
"type":"integer"
},
"message":{
"type":"text"
}
}
}
}
}
因为要对execTime字段进行排序,因此指定其类型为integer。
注意:es默认情况下进行自动类型解析的时候,会将string类型映射成text,且子类型名称和对应的类型都为keyword。因此为了保持自定义模板与默认的类型解析在这方面保持一致,上面的模板最好将子类型名称raw改成keyword。
2.创建新索引
PUT springboot-testsort
创建一个新的索引,用于reindex。根据此索引的名字可以映射到刚才创建的模板。
3.修改索引配置
PUT springboot-testsort/_settings
{
"number_of_replicas": 0,
"refresh_interval": -1
}
因为原索引的数据量很大,通过修改配置来提高reindex的效率。这里将副本数设为0(禁用副本),刷新间隔为-1(禁止刷新)。具体可参考
注意:在reindex的过程中出现gateway timeout的异常,其实并不是报错,还是正常在复制数据。
4.reindex
post _reindex?slices=20//&refresh这里如何加上了refresh则会导致setting中的-1失效
{
"source": {
"index": "springboot-2020.04.20",
"type":"applog",
"size":10000
},
"dest": {
"index": "springboot-testsort",
"type":"data"
}
}
注意:reindex的时候有个细节,就是source中的index+type的组合必须是存在的,比如这里如果index对应的type不是applog,那么就没有数据。同理对于dest来说,index+type的组合也必须是存在的,否则也没有数据。除此之外,对于dest来说,如果使用的是动态模板mapping,模板中指定了type,那么reindex的时候dest中的type需要与模板中的保持一致。
这个复制的过程可能会持续几分钟。
reindex完成之后,需要修改settings,因为没有refresh,需要修改成1s或其他指定时间,让它refresh到os内存,之后才能检索到。
PUT springboot-testsort/_settings
{
"number_of_replicas": 2,
"refresh_interval": "1s"
}
5.进行top N排序
GET springboot-testsort/data/_search
{
"_source": ["execTime"],
"query": {
"bool": {
"must":[
{
"exists":{
"field": "className"
}},
{
"term":{
"className.raw":"log.utils.LogUtil"
}
}
]
}
},
"sort" : [
{ "execTime" : {"order" : "desc"}}
],
"from": 0,
"size": 20
}