10. elasticsearch 排序

本文详细讲解了Elasticsearch中的排序策略,包括按年龄和姓名混合排序、数组字段的min/max排序、字符串字段排序以及聚合后排序实例。了解如何在实际场景中灵活运用这些技术进行高效搜索和数据组织。

1.普通排序

先按age排序再用name排序

{
  "query": {
    "match_all": {}
  }
  , 
  "sort": [
    {
      "age": { "order": "desc"},
      "name": { "order": "desc"}
    }
  ]
}

2. 数组字段排序

如果某个字段是数组,也是可以排序的,不过需要指定 mode 。mode 支持 minmaxavgsum

PUT student
{
  "mappings" : {
    "properties" : {
      "name" : {
        "type" : "keyword"
      },
      "score" : {
        "type" : "integer"
      }
    }
  }
}

# 添加文档
POST _bulk
{ "index" : { "_index" : "student", "_id" : "1" } }
{ "name" : "张三", "score": [80, 90]}
{ "index" : { "_index" : "student", "_id" : "2" } }
{ "name" : "李四", "score": [78, 95] }

 按照 score 的最小值排序:

{
  "query": {
    "match_all": {}
  },
  "sort": [
    {
      "score": {"order" : "asc", "mode": "min"}
    }
  ]
}

3.字符排序

被解析的字符串字段也是多值字段, 但是很少会按照你想要的方式进行排序。如果你想分析一个字符串,如 fine old art , 这包含 3 项。我们很可能想要按第一项的字母排序,然后按第二项的字母排序,诸如此类,但是 Elasticsearch 在排序过程中没有这样的信息。

你可以使用 min 和 max 排序模式(默认是 min ),但是这会导致排序以 art 或是 old ,任何一个都不是所希望的。

为了以字符串字段进行排序,这个字段应仅包含一项: 整个 not_analyzed 字符串。 但是我们仍需要 analyzed 字段,这样才能以全文进行查询

一个简单的方法是用两种方式对同一个字符串进行索引,这将在文档中包括两个字段: analyzed 用于搜索, not_analyzed 用于排序

 

"tweet": { 
    "type":     "string",
    "analyzer": "english",
    "fields": {
        "raw": { 
            "type":  "string",
            "index": "not_analyzed"
        }
    }
}

tweet 主字段与之前的一样: 是一个 analyzed 全文字段。

新的 tweet.raw 子字段是 not_analyzed.

{
    "query": {
        "match": {
            "tweet": "elasticsearch"
        }
    },
    "sort": "tweet.raw"
}

4. 聚合后进行排序

{
  "query": {
    "match_phrase": {
      "goods_name_simple": "工具"
    }
  },
  "size":0,
  "aggs":{
    "group_by_spuid":{
      "terms":{
        "field": "goods_commonid",
        "order" : [
          {"avg_goods_price":"desc"},
          { "top_hit":"desc"}
        ]
      },
      "aggs":{
        "avg_goods_price":{
          "avg":{
            "field":"goods_price"
          }
        },
        "top_hit" : {
          "max": {
            "script": {"source": "_score"}
          }
        }
      }
    }
  }
}
 

在 Spring Boot 3 应用中使用 Elasticsearch 8.10 的 `SearchRequest.Builder` 实现基于地理距离的排序功能,需要结合 `GeoDistanceSortBuilder` 来构建排序逻辑。Elasticsearch 提供了强大的地理空间排序能力,可以通过指定一个地理位置字段和一个参考点,对搜索结果按照距离远近进行排序。 以下是一个完整的实现示例: ### 构建带有地理距离排序的 SearchRequest ```java import co.elastic.clients.elasticsearch.core.SearchRequest; import co.elastic.clients.elasticsearch.core.search.SortOptions; import co.elastic.clients.elasticsearch.core.search.SortOrder; import co.elastic.clients.elasticsearch.core.search.GeoDistanceSort; import co.elastic.clients.elasticsearch.core.search.GeoDistanceType; import co.elastic.clients.elasticsearch.core.search.FieldSort; import co.elastic.clients.elasticsearch.core.search.SortOptions; import co.elastic.clients.elasticsearch.core.search.GeoDistanceSortBuilder; import co.elastic.clients.elasticsearch.core.search.GeoPoint; import co.elastic.clients.elasticsearch.core.search.GeoDistanceType; import co.elastic.clients.elasticsearch.core.search.SortOrder; import co.elastic.clients.elasticsearch.core.search.FieldSort; import co.elastic.clients.elasticsearch.core.search.GeoDistanceSort; import co.elastic.clients.elasticsearch.core.search.SortOptions; import java.io.IOException; import java.util.Collections; public class ElasticsearchGeoSortExample { public SearchRequest buildGeoDistanceSortRequest(String indexName, double lat, double lon) throws IOException { // 创建参考地理点 GeoPoint origin = GeoPoint.of(lat, lon); // 构建地理距离排序 GeoDistanceSort geoDistanceSort = GeoDistanceSort.of(b -> b .field("location") // 替换为你的地理字段名称 .origin(origin) .unit("km") // 排序单位为公里 .order(SortOrder.Asc) // 按照升序排列 ); // 将排序选项添加到查询中 SortOptions sortOptions = SortOptions.of(b -> b.geoDistance(geoDistanceSort)); return SearchRequest.of(b -> b .index(indexName) .sort(sortOptions) ); } } ``` ### 说明: - `location` 是 Elasticsearch 中定义为 `geo_point` 类型的字段名,表示文档的地理坐标。 - `GeoPoint.of(lat, lon)` 用于指定排序的参考点坐标。 - `.unit("km")` 表示以公里为单位计算距离。 - `.order(SortOrder.Asc)` 控制排序顺序,`Asc` 表示距离由近到远,`Desc` 则为由远到近。 ### 配置索引映射中的地理字段(如尚未定义) 确保你的索引映射中已定义了 `geo_point` 类型的字段,例如: ```json PUT /places { "mappings": { "properties": { "name": { "type": "text" }, "location": { "type": "geo_point" } } } } ``` ### 示例数据插入 ```json POST /places/_doc/1 { "name": "Shanghai Tower", "location": { "lat": 31.2304, "lon": 121.4737 } } ``` ### 相关查询行为说明 - 使用 `GeoDistanceSort` 可以动态地为每个查询指定不同的参考点。 - 排序字段必须是 `geo_point` 类型,否则会抛出异常。 - 如果需要结合查询条件,可以在 `SearchRequest.Builder` 中添加 `QueryBuilders`。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值