????????在默認(rèn)情況下,ES對搜索結(jié)果是按照相關(guān)性降序排序的。有時需要按照某些字段的值進(jìn)行升序或者降序排序。
????????ES提供了sort子句可以對數(shù)據(jù)進(jìn)行排序。使用sort子句一般是按照字段信息進(jìn)行排序,不受相關(guān)性影響,而且打分步驟需要耗費(fèi)一定的硬件資源和時間,因此默認(rèn)情況下,不對文檔進(jìn)行打分。使用sort排序分為兩種類別,一種是按照字段值的大小進(jìn)行排序,另一種是按照給定地理坐標(biāo)的距離遠(yuǎn)近進(jìn)行排序。
按普通字段值排序
????????使用sort子句對字段值進(jìn)行排序時需要指定排序的字段。ES默認(rèn)是按照字段值進(jìn)行升序排序,可以設(shè)置order參數(shù)為asc或desc,指定按照字段值進(jìn)行升序或者降序排序。以下示例為搜索名稱包含“北京”的旅館,并對旅館按照價格進(jìn)行降序排列:
GET /hotel/_search
{
"query": {
"match": {
"title": "北京"
}
},
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
????????使用sort對搜索結(jié)果排序后,在每個文檔的_source信息下面多出了一個sort信息,該信息中顯示了當(dāng)前文檔排序字段的值。另外,文檔的_score值和max_score都為null,這說明在默認(rèn)情況下ES查詢時使用sort對結(jié)果排序是不計算分?jǐn)?shù)的。也可以使用sort對搜索結(jié)果按照多個字段進(jìn)行排序。例如,用戶可以按照價格進(jìn)行降序排列,然后再按照口碑值進(jìn)行降序排列,對應(yīng)的DSL如下:
GET /hotel/_search
{
"query": {
"match": {
"title": "北京"
}
},
"sort": [
{
"price": {
"order": "desc"
},
"praise": {
"order": "desc"
}
}
]
}
在Java客戶端中對搜索結(jié)果進(jìn)行排序時,可以一次或者多次調(diào)用searchSourceBuilder.sort()方法添加一個或多個排序條件。對應(yīng)上面的排序DSL,Java代碼如下:
@Test
public void testNormalFieldSort() throws IOException {
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(Arrays.stream("127.0.0.1:9200".split(","))
.map(host->{
String[] split = host.split(":");
String hostName = split[0];
int port = Integer.parseInt(split[1]);
return new HttpHost(hostName,port,HttpHost.DEFAULT_SCHEME_NAME);
}).filter(Objects::nonNull).toArray(HttpHost[]::new)));
SearchRequest request = new SearchRequest("hotel");
request.source(new SearchSourceBuilder().query(QueryBuilders.matchQuery("title","北京")).sort("price", SortOrder.DESC)
.sort("praise",SortOrder.DESC));
SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
for (SearchHit hit:searchResponse.getHits()) {
System.out.println(hit.getSourceAsString()+" "+hit.getScore());
}
}
按地理距離排序
????????使用geo_distance查詢,配合sort可以指定另一種排序規(guī)則,即按照文檔坐標(biāo)與指定坐標(biāo)的距離對結(jié)果進(jìn)行排序。使用時,需要在sort內(nèi)部指定排序名稱為geo_distanc,并指定目的地坐標(biāo)。除了可以指定升序或者降序排列外,還可以指定排序結(jié)果中sort子句中的距離的計量單位,默認(rèn)值為km即千米。在進(jìn)行距離計算時,系統(tǒng)默認(rèn)使用的算法為arc,該算法的特點(diǎn)是計算精準(zhǔn)但是耗費(fèi)時間較長,用戶可以使用distance_type參數(shù)選擇另一種計算速度快但經(jīng)度略差的算法,名稱為plane。如下示例使用geo_distance查詢天安門5km范圍內(nèi)的旅館,并按照距離由近及遠(yuǎn)進(jìn)行排序:????????
GET /hotel/_search
{
"query": {
"geo_distance":{
"distance":"5km",
"location":{
"lat":39.915143,
"lon":116.4039
}
}
},
"sort": [
{
"_geo_distance": {
"location": {
"lat":39.915143,
"lon":116.4039
},
"order": "asc",
"unit": "km",
"distance_type": "plane"
}
}
]
}
????????在Java客戶端中對geo_distance的搜索結(jié)果進(jìn)行排序時,可以調(diào)用SortBuilders.geo DistanceSort()方法新建geo_distance查詢對象的實(shí)例,然后將該實(shí)例傳給searchSource Builder.sort()方法即可完成按照距離排序的要求。對應(yīng)上面的排序DSL,Java代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-504682.html
@Test
public void testGeoSort() throws IOException {
RestHighLevelClient restHighLevelClient = new RestHighLevelClient(RestClient.builder(Arrays.stream("127.0.0.1:9200".split(","))
.map(host->{
String[] split = host.split(":");
String hostName = split[0];
int port = Integer.parseInt(split[1]);
return new HttpHost(hostName,port,HttpHost.DEFAULT_SCHEME_NAME);
}).filter(Objects::nonNull).toArray(HttpHost[]::new)));
SearchRequest request = new SearchRequest("hotel");
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder().query(QueryBuilders.geoDistanceQuery("location").distance(5, DistanceUnit.KILOMETERS)
.point(39.915143, 116.4039));
GeoDistanceSortBuilder geoDistanceSortBuilder = SortBuilders.geoDistanceSort("location", 39.915143, 116.4039).point(39.915143, 116.4039).unit(DistanceUnit.KILOMETERS);
searchSourceBuilder.sort(geoDistanceSortBuilder);
SearchResponse searchResponse = restHighLevelClient.search(request, RequestOptions.DEFAULT);
for (SearchHit hit:searchResponse.getHits()) {
System.out.println(hit.getSourceAsString()+" "+hit.getScore());
}
}
在實(shí)際開發(fā)過程中,往往需要先寫出符合需求的查詢的DSL,然后對照DSL進(jìn)行Java編碼,最后再通過對比兩方的結(jié)果是否一致來判定程序正確與否。文章來源地址http://www.zghlxwxcb.cn/news/detail-504682.html
到了這里,關(guān)于Elasticsearch之排序解析(十二)的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!