Sort
允许在特定字段上添加一个或多个排序。 每个排序也可以颠倒。 排序是在每个字段级别上定义的,具有_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" }
}
}
注意:
_doc
除了能最有效率的排列顺序、没有真正的使用场景。所以如果你不关心文档返回的顺序,那么你应该按_doc
排序。 这特别有助于滚动。
排序值
返回的每个文档的排序值也作为响应的一部分返回。
排列顺序
排序选项可以有以下值:
选项 | 描述 |
---|---|
asc |
升序 |
desc |
降序 |
在对_score
进行排序时,该顺序默认为desc
,在对其他事物进行排序时默认为asc
。
排列模式选项
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"}}
]
}
使用内嵌对象排序
Elasticsearch 还支持根据一个或多个嵌套对象内的字段进行排序。 通过嵌套字段支持进行的排序在已经存在的排序选项之上具有以下参数:
nested_path
定义要排序的嵌套对象。 实际排序字段必须是此嵌套对象内的直接字段。 当通过嵌套字段排序时,此字段是必需的。
nested_filter
嵌套路径中的内部对象应与其匹配的过滤器,以便通过排序考虑其字段值。 常见的情况是在嵌套的过滤器或查询中重复查询/过滤。 默认情况下,没有 nested_filter 是激活的。
内嵌对象排序示例
在下面的示例中,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
参数指定如何处理缺少此字段的文档:missing
的值可以设置为_last
,_first
或自定义值(将用于缺失字段的文档的排序值)。
例如:
GET /_search
{
"sort" : [
{ "price" : {"missing" : "_last"} }
],
"query" : {
"term" : { "product" : "chocolate" }
}
}
注意
如果嵌套的内部对象与
nested_filter
不匹配,则使用缺少的值。
忽略没有映射的字段
默认地,如果没有与字段关联的映射,搜索请求将失败。 unmapped_type
选项允许忽略没有映射且没有由它们排序的字段。 此参数的值用于确定要发出的排序值。下面是一个如何使用它的例子:
GET /_search
{
"sort" : [
{ "price" : {"unmapped_type" : "long"} }
],
"query" : {
"term" : { "product" : "chocolate" }
}
}
如果查询的任何索引没有price
的映射,那么Elasticsearch将处理它,就好像存在类型为long
的映射,其中该索引中的所有文档都没有该字段的值。
GEO距离排序
允许按_geo_distance
排序。 下面是一个例子,假设pin.location
是一个类型为geo_point
的字段:
GET /_search
{
"sort" : [
{
"_geo_distance" : {
"pin.location" : [-70, 40],
"order" : "asc",
"unit" : "km",
"mode" : "min",
"distance_type" : "arc"
}
}
],
"query" : {
"term" : { "user" : "kimchy" }
}
}
distance_type
如何计算距离。 如何计算距离。可以是弧(默认)或平面(更快,但长距离不准确,靠近极点)。
mode
如果字段有多个地理点,该怎么办。 默认情况下,按升序排序时考虑最短距离,按降序排序时最长距离。 支持的值为 min,max,median 和 avg。
unit
计算排序值时使用的单位。 默认值为 m(米)。
注意
geo distance sorting
不支持可配置的缺失值:当文档没有用于距离计算的字段的值时,距离将始终被视为等于Infinity
。
在提供坐标时支持以下格式:
属性格式的经纬度
GET /_search
{
"sort" : [
{
"_geo_distance" : {
"pin.location" : {
"lat" : 40,
"lon" : -70
},
"order" : "asc",
"unit" : "km"
}
}
],
"query" : {
"term" : { "user" : "kimchy" }
}
}
字符串格式的经纬度
在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" }
}
}
经纬度数组
格式是[lon,lat]
,注意,lon/lat
的顺序在这里为了符合GeoJSON。
GET /_search
{
"sort" : [
{
"_geo_distance" : {
"pin.location" : [-70, 40],
"order" : "asc",
"unit" : "km"
}
}
],
"query" : {
"term" : { "user" : "kimchy" }
}
}
多个引用点
多个地理点可以作为一个包含任何 geo_point 格式的数组传递,例如,
GET /_search
{
"sort" : [
{
"_geo_distance" : {
"pin.location" : [[-70, 40], [-71, 42]],
"order" : "asc",
"unit" : "km"
}
}
],
"query" : {
"term" : { "user" : "kimchy" }
}
}
等等。
文档的最终距离将是包含在文档中的所有点的最小/最大/平均(通过模式定义)到在排序请求中给出的所有点的距离。
基于脚本排序
允许基于自定义脚本排序,这里是一个例子:
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
设置为true
,仍将计算和跟踪分数。
GET /_search
{
"track_scores": true,
"sort" : [
{ "post_date" : {"order" : "desc"} },
{ "name" : "desc" },
{ "age" : "desc" }
],
"query" : {
"term" : { "user" : "kimchy" }
}
}
内存注意事项
排序时,相关的排序字段值将加载到内存中。这意味着每个分片应该有足够的内存来容纳它们。对于基于字符串的类型,排序的字段不应该被analyzed
或tokenized
。对于数字类型,如果可能,建议将类型显式设置为较窄类型(如short
,integer
和float
)。