Elasticsearch 排序类型全解析:支持类型+实战示例+生产避坑
-
- 前言
- 一、核心概念:Elasticsearch 排序基础
-
- 1.1 排序原理
- 1.2 排序关键字
- 1.3 排序执行流程图
- 1.4 重要规则
- 二、Elasticsearch 支持的排序类型(全)
-
- 2.1 排序类型总览
- 三、排序类型实战示例
-
- 3.1 排序类型:数字类型排序(最常用)
- 3.2 排序类型:日期类型排序
- 3.3 排序类型:关键字字典排序
- 3.4 排序类型:文档ID排序
- 3.5 排序类型:相关性分数排序
- 3.6 排序类型:地理位置距离排序(Geo)
- 3.7 排序类型:脚本自定义排序
- 3.8 排序类型:嵌套字段排序(Nested)
- 四、多字段组合排序
- 五、常见错误与避坑指南
-
- 5.1 text 类型字段不能排序
- 5.2 排序性能低
- 5.3 中文排序乱序
- 六、排序类型总结表
- 七、总结(核心3条)
-
- 总结
|
🌺The Begin🌺点点关注,收藏不迷路🌺 |
前言
在使用 Elasticsearch 进行搜索时,排序(Sort) 是必不可少的功能。ES 支持对数字、日期、文本、地理位置、字典等多种类型进行排序,但不同字段类型的排序规则、使用方式完全不同,错误使用会导致排序失效、报错或性能低下。
本文详细讲解 Elasticsearch 支持哪些排序类型,每种排序都附带清晰定义、使用场景、可直接运行的示例,并包含流程图、注意事项,完全符合 CSDN 发布标准,适用于 ES 7.x/8.x 全版本。
一、核心概念:Elasticsearch 排序基础
1.1 排序原理
Elasticsearch 默认按相关性分数(_score)降序排序。 手动排序时,会根据字段原始值进行排序,而非分词后的值。
1.2 排序关键字
- asc:升序(从小到大)
- desc:降序(从大到小)
1.3 排序执行流程图
#mermaid-svg-aArWIEUqx1CKpfXE{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;fill:#333;}@keyframes edge-animation-frame{from{stroke-dashoffset:0;}}@keyframes dash{to{stroke-dashoffset:0;}}#mermaid-svg-aArWIEUqx1CKpfXE .edge-animation-slow{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 50s linear infinite;stroke-linecap:round;}#mermaid-svg-aArWIEUqx1CKpfXE .edge-animation-fast{stroke-dasharray:9,5!important;stroke-dashoffset:900;animation:dash 20s linear infinite;stroke-linecap:round;}#mermaid-svg-aArWIEUqx1CKpfXE .error-icon{fill:#552222;}#mermaid-svg-aArWIEUqx1CKpfXE .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-aArWIEUqx1CKpfXE .edge-thickness-normal{stroke-width:1px;}#mermaid-svg-aArWIEUqx1CKpfXE .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-aArWIEUqx1CKpfXE .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-aArWIEUqx1CKpfXE .edge-thickness-invisible{stroke-width:0;fill:none;}#mermaid-svg-aArWIEUqx1CKpfXE .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-aArWIEUqx1CKpfXE .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-aArWIEUqx1CKpfXE .marker{fill:#333333;stroke:#333333;}#mermaid-svg-aArWIEUqx1CKpfXE .marker.cross{stroke:#333333;}#mermaid-svg-aArWIEUqx1CKpfXE svg{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-aArWIEUqx1CKpfXE p{margin:0;}#mermaid-svg-aArWIEUqx1CKpfXE .label{font-family:\”trebuchet ms\”,verdana,arial,sans-serif;color:#333;}#mermaid-svg-aArWIEUqx1CKpfXE .cluster-label text{fill:#333;}#mermaid-svg-aArWIEUqx1CKpfXE .cluster-label span{color:#333;}#mermaid-svg-aArWIEUqx1CKpfXE .cluster-label span p{background-color:transparent;}#mermaid-svg-aArWIEUqx1CKpfXE .label text,#mermaid-svg-aArWIEUqx1CKpfXE span{fill:#333;color:#333;}#mermaid-svg-aArWIEUqx1CKpfXE .node rect,#mermaid-svg-aArWIEUqx1CKpfXE .node circle,#mermaid-svg-aArWIEUqx1CKpfXE .node ellipse,#mermaid-svg-aArWIEUqx1CKpfXE .node polygon,#mermaid-svg-aArWIEUqx1CKpfXE .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-aArWIEUqx1CKpfXE .rough-node .label text,#mermaid-svg-aArWIEUqx1CKpfXE .node .label text,#mermaid-svg-aArWIEUqx1CKpfXE .image-shape .label,#mermaid-svg-aArWIEUqx1CKpfXE .icon-shape .label{text-anchor:middle;}#mermaid-svg-aArWIEUqx1CKpfXE .node .katex path{fill:#000;stroke:#000;stroke-width:1px;}#mermaid-svg-aArWIEUqx1CKpfXE .rough-node .label,#mermaid-svg-aArWIEUqx1CKpfXE .node .label,#mermaid-svg-aArWIEUqx1CKpfXE .image-shape .label,#mermaid-svg-aArWIEUqx1CKpfXE .icon-shape .label{text-align:center;}#mermaid-svg-aArWIEUqx1CKpfXE .node.clickable{cursor:pointer;}#mermaid-svg-aArWIEUqx1CKpfXE .root .anchor path{fill:#333333!important;stroke-width:0;stroke:#333333;}#mermaid-svg-aArWIEUqx1CKpfXE .arrowheadPath{fill:#333333;}#mermaid-svg-aArWIEUqx1CKpfXE .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-aArWIEUqx1CKpfXE .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-aArWIEUqx1CKpfXE .edgeLabel{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aArWIEUqx1CKpfXE .edgeLabel p{background-color:rgba(232,232,232, 0.8);}#mermaid-svg-aArWIEUqx1CKpfXE .edgeLabel rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aArWIEUqx1CKpfXE .labelBkg{background-color:rgba(232, 232, 232, 0.5);}#mermaid-svg-aArWIEUqx1CKpfXE .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-aArWIEUqx1CKpfXE .cluster text{fill:#333;}#mermaid-svg-aArWIEUqx1CKpfXE .cluster span{color:#333;}#mermaid-svg-aArWIEUqx1CKpfXE div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:\”trebuchet ms\”,verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-aArWIEUqx1CKpfXE .flowchartTitleText{text-anchor:middle;font-size:18px;fill:#333;}#mermaid-svg-aArWIEUqx1CKpfXE rect.text{fill:none;stroke-width:0;}#mermaid-svg-aArWIEUqx1CKpfXE .icon-shape,#mermaid-svg-aArWIEUqx1CKpfXE .image-shape{background-color:rgba(232,232,232, 0.8);text-align:center;}#mermaid-svg-aArWIEUqx1CKpfXE .icon-shape p,#mermaid-svg-aArWIEUqx1CKpfXE .image-shape p{background-color:rgba(232,232,232, 0.8);padding:2px;}#mermaid-svg-aArWIEUqx1CKpfXE .icon-shape .label rect,#mermaid-svg-aArWIEUqx1CKpfXE .image-shape .label rect{opacity:0.5;background-color:rgba(232,232,232, 0.8);fill:rgba(232,232,232, 0.8);}#mermaid-svg-aArWIEUqx1CKpfXE .label-icon{display:inline-block;height:1em;overflow:visible;vertical-align:-0.125em;}#mermaid-svg-aArWIEUqx1CKpfXE .node .label-icon path{fill:currentColor;stroke:revert;stroke-width:revert;}#mermaid-svg-aArWIEUqx1CKpfXE :root{–mermaid-font-family:\”trebuchet ms\”,verdana,arial,sans-serif;}
指定排序字段+规则
ES提取字段原始值
按asc/desc排序
返回排序后结果
展示有序数据
1.4 重要规则
二、Elasticsearch 支持的排序类型(全)
2.1 排序类型总览
下面逐一详细说明。
三、排序类型实战示例
3.1 排序类型:数字类型排序(最常用)
标题格式:排序类型:数字类型排序(integer/long/float)
- 适用字段:价格、年龄、销量、序号
- 支持:升序、降序
- 示例:按价格降序
GET /product/_search
{
"sort": [
{
"price": {
"order": "desc"
}
}
]
}
3.2 排序类型:日期类型排序
标题格式:排序类型:日期类型排序(date)
- 适用字段:创建时间、更新时间、发布时间
- 示例:按创建时间最新在前
GET /article/_search
{
"sort": [
{
"create_time": {
"order": "desc"
}
}
]
}
3.3 排序类型:关键字字典排序
标题格式:排序类型:keyword 字典排序
- 适用字段:用户名、分类、标签
- 必须是 keyword 类型,text 类型不能排序
- 示例:按用户名 A-Z 升序
GET /user/_search
{
"sort": [
{
"username.keyword": {
"order": "asc"
}
}
]
}
3.4 排序类型:文档ID排序
标题格式:排序类型:文档ID _id 排序
- 按文档ID字典序排序
GET /user/_search
{
"sort": [
{
"_id": {
"order": "asc"
}
}
]
}
3.5 排序类型:相关性分数排序
标题格式:排序类型:相关性分数 _score 排序
- 默认排序方式
- 搜索匹配度越高,分数越高
GET /product/_search
{
"query": {
"match": {
"name": "手机"
}
},
"sort": [
{
"_score": {
"order": "desc"
}
}
]
}
3.6 排序类型:地理位置距离排序(Geo)
标题格式:排序类型:地理位置距离排序(geo_distance)
- 适用场景:附近的店、离我最近、地理排序
- 示例:按离目标坐标距离由近到远排序
GET /shop/_search
{
"sort": [
{
"_geo_distance": {
"location": {
"lat": 39.9,
"lon": 116.4
},
"order": "asc",
"unit": "km"
}
}
]
}
3.7 排序类型:脚本自定义排序
标题格式:排序类型:脚本自定义排序(Script)
- 自定义计算规则后排序
- 示例:价格 * 2 后排序
GET /product/_search
{
"sort": {
"_script": {
"type": "number",
"script": {
"lang": "painless",
"source": "doc['price'].value * 2"
},
"order": "desc"
}
}
}
3.8 排序类型:嵌套字段排序(Nested)
标题格式:排序类型:嵌套字段排序(nested)
- 对 nested 类型子字段排序
- 示例:按子对象中的价格排序
GET /order/_search
{
"sort": [
{
"items.price": {
"order": "desc",
"nested": {
"path": "items"
}
}
}
]
}
四、多字段组合排序
标题格式:排序类型:多字段组合排序
- 先按销量降序,销量相同按价格升序
GET /product/_search
{
"sort": [
{ "sales": { "order": "desc" } },
{ "price": { "order": "asc" } }
]
}
五、常见错误与避坑指南
5.1 text 类型字段不能排序
- 错误:Fielddata is disabled on text fields
- 原因:text 分词后无法排序
- 解决:使用 .keyword 后缀
5.2 排序性能低
- 原因:排序字段未使用 doc_values
- 解决:使用 keyword、数字、日期类型
5.3 中文排序乱序
- 解决:使用 keyword 类型 + 拼音分词器
六、排序类型总结表
| 数字排序 | integer/long/float | 价格、销量、年龄 |
| 日期排序 | date | 时间、创建时间 |
| 字典排序 | keyword | 用户名、分类 |
| ID排序 | _id | 文档ID |
| 相关性排序 | _score | 搜索匹配度 |
| 地理位置排序 | geo_point | 附近店铺 |
| 脚本排序 | 任意 | 自定义计算排序 |
| 嵌套排序 | nested | 子字段排序 |
七、总结(核心3条)
总结

|
🌺The End🌺点点关注,收藏不迷路🌺 |


