# Sort

原文链接 : [https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html](https://www.elastic.co/guide/en/elasticsearch/reference/current/search-request-sort.html)

译文链接 : [http://www.apache.wiki/pages/editpage.action?pageId=48830](http://www.apache.wiki/pages/editpage.action?pageId=4883051)78

贡献者 : [ping](/display/~wangyangting)

允许在特定字段上添加一个或多个排序。 每个排序也可以颠倒。 排序是在每个字段级别上定义的，具有 _score 的特殊字段名称按分数排序，_doc 按索引顺序排序。

假设以下索引映射：

```
PUT /my_index
{
    "mappings": {
        "my_type": {
            "properties": {
                "post_date": { "type": "date" },
                "user": {
                    "type": "keyword"
                },
                "name": {
                    "type": "keyword"
                },
                "age": { "type": "integer" }
            }
        }
    }
}
```

```
GET /my_index/my_type/_search
{
    "sort" : [
        { "post_date" : {"order" : "asc"}},
        "user",
        { "name" : "desc" },
        { "age" : "desc" },
        "_score"
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
```

Note: 

_doc 除了是最有效的排序顺序没有真正的用例。所以如果你不关心文档返回的顺序，那么你应该按 _doc 排序。 这特别有助于滚动。

## Sort Values

返回的每个文档的排序值也作为响应的一部分返回。

## Sort Order

排序选项可以有以下值：

| `asc` | 按升序排序 |
| `desc` | 按倒序排序 |

在对 _score 进行排序时，该顺序默认为 desc，在对其他事物进行排序时默认为 asc。 

Sort mode Option

Elasticsearch支持按数组或多值字段排序。 mode 选项控制选择用于对其所属文档进行排序的数组值。 mode 选项可以具有以下值：

| `min` | 选择最低值。 |
| `max` | 选择最高值。 |
| `sum` | 使用所有值的和作为排序值。 仅适用于基于数字的数组字段。 |
| `avg` | 使用所有值的平均值作为排序值。 仅适用于基于数字的数组字段。 |
| `median` | 使用所有值的中值作为排序值。 仅适用于基于数字的数组字段。 |

排序模式示例用法

在下面的示例中，每个文档字段价格有多个价格。 在这种情况下，结果匹配将按基于每个文档的平均价格的升序排序。

```
PUT /my_index/my_type/1?refresh
{
   "product": "chocolate",
    "price": [20, 4]
}

POST /_search
{
   "query" : {
      "term" : { "product" : "chocolate" }
   },
   "sort" : [
      {"price" : {"order" : "asc", "mode" : "avg"}}
   ]
}

```

### Sorting within nested objects

Elasticsearch 还支持根据一个或多个嵌套对象内的字段进行排序。 通过嵌套字段支持进行的排序在已经存在的排序选项之上具有以下参数：

nested_path
定义要排序的嵌套对象。 实际排序字段必须是此嵌套对象内的直接字段。 当通过嵌套字段排序时，此字段是必需的。

nested_filter

嵌套路径中的内部对象应与其匹配的过滤器，以便通过排序考虑其字段值。 常见的情况是在嵌套的过滤器或查询中重复查询/过滤。 默认情况下，没有 nested_filter 是激活的。

Nested sorting example

在下面的示例中，offer是一个类型为嵌套的字段。 需要指定nested_path; 否则，elasticsearch不知道需要捕获哪个嵌套级排序值。

```
POST /_search
{
   "query" : {
      "term" : { "product" : "chocolate" }
   },
   "sort" : [
       {
          "offer.price" : {
             "mode" :  "avg",
             "order" : "asc",
             "nested_path" : "offer",
             "nested_filter" : {
                "term" : { "offer.color" : "blue" }
             }
          }
       }
    ]
}
```

当通过脚本排序和按地理距离排序时，也支持嵌套排序。

### Missing Values

缺少的参数指定应如何处理缺少字段的文档：缺少的值可以设置为 _last，_first 或自定义值（将用于缺少文档作为排序值）。

例如：

```
GET /_search
{
    "sort" : [
        { "price" : {"missing" : "_last"} }
    ],
    "query" : {
        "term" : { "product" : "chocolate" }
    }
}
```

Note：

如果嵌套的内部对象与 nested_filter 不匹配，则使用缺少的值。

### Ignoring Unmapped Fields

默认地，如果没有与字段关联的映射，搜索请求将失败。 unmapped_type 选项允许忽略没有映射且没有由它们排序的字段。 此参数的值用于确定要发出的排序值。下面是一个如何使用它的例子：

```
GET /_search
{
    "sort" : [
        { "price" : {"unmapped_type" : "long"} }
    ],
    "query" : {
        "term" : { "product" : "chocolate" }
    }
}
```

如果查询的任何索引没有价格的映射，那么Elasticsearch将处理它，就好像存在类型为 **long** 的映射，其中该索引中的所有文档都没有该字段的值。

### Geo Distance Sorting

允许按 _geo_distance 排序。 下面是一个例子，假设 pin.location 是一个类型为 geo_point 的字段：

```
GET /_search
{
    "sort" : [
        {
            "_geo_distance" : {
                "pin.location" : [-70, 40],
                "order" : "asc",
                "unit" : "km",
                "mode" : "min",
                "distance_type" : "sloppy_arc"
            }
        }
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
```

**distance_type**

如何计算距离。 可以是 sloppy_arc（默认），弧（稍微更精确但显着更慢）或平面（更快，但不准确在长距离和接近极点）。
**mode**
如果字段有多个地理点，该怎么办。 默认情况下，按升序排序时考虑最短距离，按降序排序时最长距离。 支持的值为 min，max，median 和 avg。
**unit**
计算排序值时使用的单位。 默认值为 m（米）。

geo distance sorting 不支持可配置的缺失值：当文档没有用于距离计算的字段的值时，距离将始终被视为等于 Infinity。

在提供坐标时支持以下格式：

#### Lat Lon as Properties

```
GET /_search
{
    "sort" : [
        {
            "_geo_distance" : {
                "pin.location" : {
                    "lat" : 40,
                    "lon" : -70
                },
                "order" : "asc",
                "unit" : "km"
            }
        }
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
```

#### Lat Lon as String

在 lat，lon 中的格式。

```
GET /_search
{
    "sort" : [
        {
            "_geo_distance" : {
                "pin.location" : "40,-70",
                "order" : "asc",
                "unit" : "km"
            }
        }
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
```

#### Geohash

```
GET /_search
{
    "sort" : [
        {
            "_geo_distance" : {
                "pin.location" : "drm3btev3e86",
                "order" : "asc",
                "unit" : "km"
            }
        }
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
```

#### Lat Lon as Array

格式在 [lon，lat]，注意，lon / lat 的顺序在这里为了符合 GeoJSON。

```
GET /_search
{
    "sort" : [
        {
            "_geo_distance" : {
                "pin.location" : [-70, 40],
                "order" : "asc",
                "unit" : "km"
            }
        }
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
```

### Multiple reference points

多个地理点可以作为一个包含任何 geo_point 格式的数组传递，例如，

```
GET /_search
{
    "sort" : [
        {
            "_geo_distance" : {
                "pin.location" : [[-70, 40], [-71, 42]],
                "order" : "asc",
                "unit" : "km"
            }
        }
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
```

等等。

文档的最终距离将是包含在文档中的所有点的最小/最大/平均（通过模式定义）到在排序请求中给出的所有点的距离。

### Script Based Sorting

允许基于自定义脚本排序，这里是一个例子：

```
GET /_search
{
    "query" : {
        "term" : { "user" : "kimchy" }
    },
    "sort" : {
        "_script" : {
            "type" : "number",
            "script" : {
                "lang": "painless",
                "inline": "doc['field_name'].value * params.factor",
                "params" : {
                    "factor" : 1.1
                }
            },
            "order" : "asc"
        }
    }
}
```

### Track Scores

在字段上排序时，不会计算分数。 通过将 track_scores 设置为 true，仍将计算和跟踪分数。

```
GET /_search
{
    "track_scores": true,
    "sort" : [
        { "post_date" : {"order" : "desc"} },
        { "name" : "desc" },
        { "age" : "desc" }
    ],
    "query" : {
        "term" : { "user" : "kimchy" }
    }
}
```

### Memory Considerations

当排序时，相关的排序字段值被加载到存储器中。 这意味着每个分片，应该有足够的内存来容纳它们。 对于基于字符串的类型，排序的字段不应被分析/标记化。 对于数字类型，如果可能，建议明确设置类型为更窄的类型（如 short，integer 和 float ）。