5.3 排序 (Sorting)


文档摘要

5.3 排序 (Sorting) 5.3 排序 (Sorting) 在 Elasticsearch 中,排序 (Sorting) 是一个至关重要的功能,它允许你按照一个或多个字段的值来排列搜索结果。这对于提供用户友好的搜索体验至关重要,因为用户通常希望看到最相关的结果排在最前面。 5.3.1 基础排序 最简单的排序方式是按照单个字段的升序或降序排列。 默认情况下,Elasticsearch 按照相关性评分 降序排列。 代码示例: 假设我们有一个名为 的索引,其中包含 (产品名称) 和 (价格) 字段。 我们想按照价格升序排列结果。 详解: :指定要搜索的索引。 : 匹配所有文档 :定义排序规则的数组。 :要排序的字段。

5.3 排序 (Sorting)

5.3 排序 (Sorting)

在 Elasticsearch 中,排序 (Sorting) 是一个至关重要的功能,它允许你按照一个或多个字段的值来排列搜索结果。这对于提供用户友好的搜索体验至关重要,因为用户通常希望看到最相关的结果排在最前面。

5.3.1 基础排序

最简单的排序方式是按照单个字段的升序或降序排列。 默认情况下,Elasticsearch 按照相关性评分 _score 降序排列。

代码示例:

假设我们有一个名为 products 的索引,其中包含 name (产品名称) 和 price (价格) 字段。 我们想按照价格升序排列结果。

GET /products/_search { "query": { "match_all": {} }, "sort": [ { "price": { "order": "asc" } } ] }

详解:

  • GET /products/_search:指定要搜索的索引。

  • query: 匹配所有文档

  • sort:定义排序规则的数组。

    • price:要排序的字段。

    • order: 排序顺序,asc 表示升序 (ascending),desc 表示降序 (descending)。

响应示例:

{ "took": 3, "timed_out": false, "_shards": { "total": 1, "successful": 1, "skipped": 0, "failed": 0 }, "hits": { "total": 10, "max_score": null, "hits": [ { "_index": "products", "_type": "product", "_id": "1", "_score": null, "_source": { "name": "Product A", "price": 10 }, "sort": [ 10 ] }, { "_index": "products", "_type": "product", "_id": "2", "_score": null, "_source": { "name": "Product B", "price": 20 }, "sort": [ 20 ] }, // ... 更多结果 ] } }

简写形式:

如果只需要指定字段和排序顺序,可以使用更简洁的语法:

GET /products/_search { "query": { "match_all": {} }, "sort": [ { "price": "asc" } ] }

5.3.2 多字段排序

Elasticsearch 允许你按照多个字段进行排序。 这对于在第一个字段的值相等时,使用第二个字段进行进一步排序非常有用。

代码示例:

假设我们想先按照价格升序排序,然后按照产品名称升序排序。

GET /products/_search { "query": { "match_all": {} }, "sort": [ { "price": { "order": "asc" } }, { "name": { "order": "asc" } } ] }

详解:

  • sort 数组中的每个元素都定义了一个排序规则。

  • Elasticsearch 会按照数组中规则的顺序依次进行排序。 首先按照 price 升序排序,如果 price 相同,则按照 name 升序排序。

5.3.3 缺失值处理 (Missing Values)

当排序字段的值缺失时,Elasticsearch 提供了 missing 参数来控制如何处理这些文档。

代码示例:

假设某些产品没有 price 字段。 我们想将没有 price 的产品排在最后。

GET /products/_search { "query": { "match_all": {} }, "sort": [ { "price": { "order": "asc", "missing": "_last" } } ] }

详解:

  • missing: 指定缺失值的处理方式。

    • _last: 将缺失值的文档排在最后。

    • _first: 将缺失值的文档排在最前面。

    • 你也可以指定一个具体的值,例如 0,将缺失值视为 0 进行排序。

5.3.4 基于地理位置排序 (Geo Distance Sorting)

如果你的索引包含地理位置信息,你可以根据与指定位置的距离进行排序。

代码示例:

假设我们有一个名为 restaurants 的索引,其中包含 location (地理位置) 字段。 我们想按照餐厅与指定坐标 (纬度 40.7158, 经度 -74.0056) 的距离升序排列结果。

GET /restaurants/_search { "query": { "match_all": {} }, "sort": [ { "_geo_distance": { "location": { "lat": 40.7158, "lon": -74.0056 }, "order": "asc", "unit": "km", "mode": "min" } } ] }

详解:

  • _geo_distance: 指定按照地理距离排序。

    • location: 地理位置字段。

    • lat: 纬度。

    • lon: 经度。

    • order: 排序顺序。

    • unit: 距离单位 (例如,kmmmiles)。

    • mode: 当一个文档有多个地理坐标时,计算距离的方式。 默认为 min,表示使用最近的距离。 其他选项包括 maxavg

5.3.5 基于脚本排序 (Script-Based Sorting)

Elasticsearch 允许你使用脚本来定义更复杂的排序逻辑。

代码示例:

假设我们想按照 pricediscount 的组合值进行排序。

GET /products/_search { "query": { "match_all": {} }, "sort": [ { "_script": { "script": { "source": "doc['price'].value * (1 - doc['discount'].value)", "lang": "painless" }, "order": "asc", "type": "number" } } ] }

详解:

  • _script: 指定使用脚本排序。

    • script: 定义脚本。

      • source: 脚本代码。 这里使用 Painless 脚本语言计算 price * (1 - discount)

      • lang: 脚本语言。

    • order: 排序顺序。

    • type: 脚本返回值的类型。

安全注意事项:

  • 使用脚本排序可能会影响性能,因为它需要为每个文档执行脚本。

  • 在生产环境中,应谨慎使用脚本排序,并确保脚本是安全和高效的。

5.3.6 排序的流程图

5.3.7 优化排序性能

  • 避免在非索引字段上排序: 在非索引字段上排序会导致全表扫描,影响性能。 确保用于排序的字段已正确索引。

  • 使用 doc values: 对于数值、日期和地理位置等字段,Elasticsearch 使用 doc values 来加速排序。 确保这些字段启用了 doc values。

  • 限制返回结果的数量: 使用 size 参数限制返回结果的数量可以减少排序的开销。

  • 使用缓存: Elasticsearch 会缓存查询结果,包括排序结果。 合理配置缓存可以提高性能。

  • 避免过度使用脚本排序: 脚本排序会影响性能,应尽量避免使用。

5.3.8 总结

Elasticsearch 的排序功能非常强大,可以满足各种排序需求。 通过合理使用排序参数,可以优化搜索结果的呈现方式,提高用户体验。 理解不同排序方式的特点和性能影响,可以帮助你选择最适合的排序策略。


发布者: 作者: 转发
评论区 (0)
U