对搜索结果进行排序
编辑对搜索结果进行排序
编辑允许您在特定字段上添加一个或多个排序。每个排序也可以反转。排序是在每个字段级别定义的,使用特殊的字段名 _score
按分数排序,使用 _doc
按索引顺序排序。
假设有以下索引映射
resp = client.indices.create( index="my-index-000001", mappings={ "properties": { "post_date": { "type": "date" }, "user": { "type": "keyword" }, "name": { "type": "keyword" }, "age": { "type": "integer" } } }, ) print(resp)
response = client.indices.create( index: 'my-index-000001', body: { mappings: { properties: { post_date: { type: 'date' }, user: { type: 'keyword' }, name: { type: 'keyword' }, age: { type: 'integer' } } } } ) puts response
res, err := es.Indices.Create( "my-index-000001", es.Indices.Create.WithBody(strings.NewReader(`{ "mappings": { "properties": { "post_date": { "type": "date" }, "user": { "type": "keyword" }, "name": { "type": "keyword" }, "age": { "type": "integer" } } } }`)), ) fmt.Println(res, err)
const response = await client.indices.create({ index: "my-index-000001", mappings: { properties: { post_date: { type: "date", }, user: { type: "keyword", }, name: { type: "keyword", }, age: { type: "integer", }, }, }, }); console.log(response);
PUT /my-index-000001 { "mappings": { "properties": { "post_date": { "type": "date" }, "user": { "type": "keyword" }, "name": { "type": "keyword" }, "age": { "type": "integer" } } } }
resp = client.search( index="my-index-000001", sort=[ { "post_date": { "order": "asc", "format": "strict_date_optional_time_nanos" } }, "user", { "name": "desc" }, { "age": "desc" }, "_score" ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( index: 'my-index-000001', body: { sort: [ { post_date: { order: 'asc', format: 'strict_date_optional_time_nanos' } }, 'user', { name: 'desc' }, { age: 'desc' }, '_score' ], query: { term: { user: 'kimchy' } } } ) puts response
const response = await client.search({ index: "my-index-000001", sort: [ { post_date: { order: "asc", format: "strict_date_optional_time_nanos", }, }, "user", { name: "desc", }, { age: "desc", }, "_score", ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /my-index-000001/_search { "sort" : [ { "post_date" : {"order" : "asc", "format": "strict_date_optional_time_nanos"}}, "user", { "name" : "desc" }, { "age" : "desc" }, "_score" ], "query" : { "term" : { "user" : "kimchy" } } }
_doc
除了是最有效的排序顺序之外,没有实际的用例。因此,如果您不关心文档返回的顺序,则应按 _doc
排序。这在滚动时尤其有用。
排序值
编辑搜索响应包括每个文档的 sort
值。使用 format
参数为 date
和 date_nanos
字段的 sort
值指定一个 日期格式。以下搜索以 strict_date_optional_time_nanos
格式返回 post_date
字段的 sort
值。
resp = client.search( index="my-index-000001", sort=[ { "post_date": { "format": "strict_date_optional_time_nanos" } } ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( index: 'my-index-000001', body: { sort: [ { post_date: { format: 'strict_date_optional_time_nanos' } } ], query: { term: { user: 'kimchy' } } } ) puts response
const response = await client.search({ index: "my-index-000001", sort: [ { post_date: { format: "strict_date_optional_time_nanos", }, }, ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /my-index-000001/_search { "sort" : [ { "post_date" : {"format": "strict_date_optional_time_nanos"}} ], "query" : { "term" : { "user" : "kimchy" } } }
排序顺序
编辑order
选项可以具有以下值:
|
按升序排序 |
|
按降序排序 |
当按 _score
排序时,顺序默认为 desc
,当按其他任何内容排序时,默认为 asc
。
排序模式选项
编辑Elasticsearch 支持按数组或多值字段进行排序。 mode
选项控制选择哪个数组值来对其所属的文档进行排序。 mode
选项可以具有以下值:
|
选择最小值。 |
|
选择最大值。 |
|
使用所有值的总和作为排序值。仅适用于基于数字的数组字段。 |
|
使用所有值的平均值作为排序值。仅适用于基于数字的数组字段。 |
|
使用所有值的中位数作为排序值。仅适用于基于数字的数组字段。 |
升序排序中的默认排序模式是 min
— 选择最小值。降序排序中的默认排序模式是 max
— 选择最大值。
排序模式示例用法
编辑在以下示例中,字段 price 每个文档有多个价格。在这种情况下,结果命中将按每个文档的平均价格以升序排序。
resp = client.index( index="my-index-000001", id="1", refresh=True, document={ "product": "chocolate", "price": [ 20, 4 ] }, ) print(resp) resp1 = client.search( query={ "term": { "product": "chocolate" } }, sort=[ { "price": { "order": "asc", "mode": "avg" } } ], ) print(resp1)
response = client.index( index: 'my-index-000001', id: 1, refresh: true, body: { product: 'chocolate', price: [ 20, 4 ] } ) puts response response = client.search( body: { query: { term: { product: 'chocolate' } }, sort: [ { price: { order: 'asc', mode: 'avg' } } ] } ) puts response
{ res, err := es.Index( "my-index-000001", strings.NewReader(`{ "product": "chocolate", "price": [ 20, 4 ] }`), es.Index.WithDocumentID("1"), es.Index.WithRefresh("true"), es.Index.WithPretty(), ) fmt.Println(res, err) } { res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "query": { "term": { "product": "chocolate" } }, "sort": [ { "price": { "order": "asc", "mode": "avg" } } ] }`)), es.Search.WithPretty(), ) fmt.Println(res, err) }
const response = await client.index({ index: "my-index-000001", id: 1, refresh: "true", document: { product: "chocolate", price: [20, 4], }, }); console.log(response); const response1 = await client.search({ query: { term: { product: "chocolate", }, }, sort: [ { price: { order: "asc", mode: "avg", }, }, ], }); console.log(response1);
PUT /my-index-000001/_doc/1?refresh { "product": "chocolate", "price": [20, 4] } POST /_search { "query" : { "term" : { "product" : "chocolate" } }, "sort" : [ {"price" : {"order" : "asc", "mode" : "avg"}} ] }
排序数值字段
编辑对于数值字段,也可以使用 numeric_type
选项将值从一种类型转换为另一种类型。此选项接受以下值:["double", "long", "date", "date_nanos"
],对于在映射不同的排序字段的多个数据流或索引之间进行搜索非常有用。
例如考虑以下两个索引
resp = client.indices.create( index="index_double", mappings={ "properties": { "field": { "type": "double" } } }, ) print(resp)
response = client.indices.create( index: 'index_double', body: { mappings: { properties: { field: { type: 'double' } } } } ) puts response
res, err := es.Indices.Create( "index_double", es.Indices.Create.WithBody(strings.NewReader(`{ "mappings": { "properties": { "field": { "type": "double" } } } }`)), ) fmt.Println(res, err)
const response = await client.indices.create({ index: "index_double", mappings: { properties: { field: { type: "double", }, }, }, }); console.log(response);
PUT /index_double { "mappings": { "properties": { "field": { "type": "double" } } } }
resp = client.indices.create( index="index_long", mappings={ "properties": { "field": { "type": "long" } } }, ) print(resp)
response = client.indices.create( index: 'index_long', body: { mappings: { properties: { field: { type: 'long' } } } } ) puts response
res, err := es.Indices.Create( "index_long", es.Indices.Create.WithBody(strings.NewReader(`{ "mappings": { "properties": { "field": { "type": "long" } } } }`)), ) fmt.Println(res, err)
const response = await client.indices.create({ index: "index_long", mappings: { properties: { field: { type: "long", }, }, }, }); console.log(response);
PUT /index_long { "mappings": { "properties": { "field": { "type": "long" } } } }
由于 field
在第一个索引中映射为 double
,在第二个索引中映射为 long
,因此默认情况下无法使用此字段对查询这两个索引的请求进行排序。但是,您可以使用 numeric_type
选项将类型强制为一种或另一种类型,以便为所有索引强制指定特定类型
$params = [ 'index' => 'index_long,index_double', 'body' => [ 'sort' => [ [ 'field' => [ 'numeric_type' => 'double', ], ], ], ], ]; $response = $client->search($params);
resp = client.search( index="index_long,index_double", sort=[ { "field": { "numeric_type": "double" } } ], ) print(resp)
response = client.search( index: 'index_long,index_double', body: { sort: [ { field: { numeric_type: 'double' } } ] } ) puts response
res, err := es.Search( es.Search.WithIndex("index_long,index_double"), es.Search.WithBody(strings.NewReader(`{ "sort": [ { "field": { "numeric_type": "double" } } ] }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ index: "index_long,index_double", sort: [ { field: { numeric_type: "double", }, }, ], }); console.log(response);
POST /index_long,index_double/_search { "sort" : [ { "field" : { "numeric_type" : "double" } } ] }
在上面的示例中,为了与 index_double
索引生成的值兼容,index_long
索引的值将转换为 double。也可以将浮点字段转换为 long
,但请注意,在这种情况下,浮点数将替换为小于或等于(如果该值是负数,则大于或等于)参数且等于数学整数的最大值。
此选项还可用于将使用毫秒分辨率的 date
字段转换为具有纳秒分辨率的 date_nanos
字段。例如考虑以下两个索引
resp = client.indices.create( index="index_double", mappings={ "properties": { "field": { "type": "date" } } }, ) print(resp)
response = client.indices.create( index: 'index_double', body: { mappings: { properties: { field: { type: 'date' } } } } ) puts response
res, err := es.Indices.Create( "index_double", es.Indices.Create.WithBody(strings.NewReader(`{ "mappings": { "properties": { "field": { "type": "date" } } } }`)), ) fmt.Println(res, err)
const response = await client.indices.create({ index: "index_double", mappings: { properties: { field: { type: "date", }, }, }, }); console.log(response);
PUT /index_double { "mappings": { "properties": { "field": { "type": "date" } } } }
resp = client.indices.create( index="index_long", mappings={ "properties": { "field": { "type": "date_nanos" } } }, ) print(resp)
response = client.indices.create( index: 'index_long', body: { mappings: { properties: { field: { type: 'date_nanos' } } } } ) puts response
res, err := es.Indices.Create( "index_long", es.Indices.Create.WithBody(strings.NewReader(`{ "mappings": { "properties": { "field": { "type": "date_nanos" } } } }`)), ) fmt.Println(res, err)
const response = await client.indices.create({ index: "index_long", mappings: { properties: { field: { type: "date_nanos", }, }, }, }); console.log(response);
PUT /index_long { "mappings": { "properties": { "field": { "type": "date_nanos" } } } }
这些索引中的值以不同的分辨率存储,因此对这些字段进行排序将始终按 date
在 date_nanos
之前排序(升序)。使用 numeric_type
类型选项,可以为排序设置单个分辨率,设置为 date
会将 date_nanos
转换为毫秒分辨率,而 date_nanos
会将 date
字段中的值转换为纳秒分辨率
$params = [ 'index' => 'index_long,index_double', 'body' => [ 'sort' => [ [ 'field' => [ 'numeric_type' => 'date_nanos', ], ], ], ], ]; $response = $client->search($params);
resp = client.search( index="index_long,index_double", sort=[ { "field": { "numeric_type": "date_nanos" } } ], ) print(resp)
res, err := es.Search( es.Search.WithIndex("index_long,index_double"), es.Search.WithBody(strings.NewReader(`{ "sort": [ { "field": { "numeric_type": "date_nanos" } } ] }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ index: "index_long,index_double", sort: [ { field: { numeric_type: "date_nanos", }, }, ], }); console.log(response);
POST /index_long,index_double/_search { "sort" : [ { "field" : { "numeric_type" : "date_nanos" } } ] }
为避免溢出,对 1970 年之前和 2262 年之后的日期不能应用转换为 date_nanos
,因为纳秒表示为 longs。
在嵌套对象中排序。
编辑Elasticsearch 还支持按一个或多个嵌套对象内的字段进行排序。按嵌套字段排序支持具有 nested
排序选项,该选项具有以下属性
-
path
- 定义要对哪个嵌套对象进行排序。实际的排序字段必须是此嵌套对象内的直接字段。按嵌套字段排序时,此字段是必需的。
-
filter
- 嵌套路径内的内部对象应该匹配的过滤器,以便排序时考虑其字段值。常见情况是在嵌套过滤器或查询中重复查询/过滤器。默认情况下,没有激活任何
filter
。 -
max_children
- 在选择排序值时,每个根文档要考虑的最大子项数。默认为无限制。
-
nested
- 与顶层
nested
相同,但适用于当前嵌套对象内的另一个嵌套路径。
如果在没有 nested
上下文的情况下在排序中定义了嵌套字段,则 Elasticsearch 将引发错误。
嵌套排序示例
编辑在下面的示例中,offer
是 nested
类型的字段。需要指定嵌套的 path
;否则,Elasticsearch 不知道需要在哪个嵌套级别捕获排序值。
$params = [ 'body' => [ 'query' => [ 'term' => [ 'product' => 'chocolate', ], ], 'sort' => [ [ 'offer.price' => [ 'mode' => 'avg', 'order' => 'asc', 'nested' => [ 'path' => 'offer', 'filter' => [ 'term' => [ 'offer.color' => 'blue', ], ], ], ], ], ], ], ]; $response = $client->search($params);
resp = client.search( query={ "term": { "product": "chocolate" } }, sort=[ { "offer.price": { "mode": "avg", "order": "asc", "nested": { "path": "offer", "filter": { "term": { "offer.color": "blue" } } } } } ], ) print(resp)
response = client.search( body: { query: { term: { product: 'chocolate' } }, sort: [ { 'offer.price' => { mode: 'avg', order: 'asc', nested: { path: 'offer', filter: { term: { 'offer.color' => 'blue' } } } } } ] } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "query": { "term": { "product": "chocolate" } }, "sort": [ { "offer.price": { "mode": "avg", "order": "asc", "nested": { "path": "offer", "filter": { "term": { "offer.color": "blue" } } } } } ] }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ query: { term: { product: "chocolate", }, }, sort: [ { "offer.price": { mode: "avg", order: "asc", nested: { path: "offer", filter: { term: { "offer.color": "blue", }, }, }, }, }, ], }); console.log(response);
POST /_search { "query" : { "term" : { "product" : "chocolate" } }, "sort" : [ { "offer.price" : { "mode" : "avg", "order" : "asc", "nested": { "path": "offer", "filter": { "term" : { "offer.color" : "blue" } } } } } ] }
在下面的示例中,parent
和 child
字段是 nested
类型。需要在每个级别指定 nested.path
;否则,Elasticsearch 不知道需要在哪个嵌套级别捕获排序值。
$params = [ 'body' => [ 'query' => [ 'nested' => [ 'path' => 'parent', 'query' => [ 'bool' => [ 'must' => [ 'range' => [ 'parent.age' => [ 'gte' => 21, ], ], ], 'filter' => [ 'nested' => [ 'path' => 'parent.child', 'query' => [ 'match' => [ 'parent.child.name' => 'matt', ], ], ], ], ], ], ], ], 'sort' => [ [ 'parent.child.age' => [ 'mode' => 'min', 'order' => 'asc', 'nested' => [ 'path' => 'parent', 'filter' => [ 'range' => [ 'parent.age' => [ 'gte' => 21, ], ], ], 'nested' => [ 'path' => 'parent.child', 'filter' => [ 'match' => [ 'parent.child.name' => 'matt', ], ], ], ], ], ], ], ], ]; $response = $client->search($params);
resp = client.search( query={ "nested": { "path": "parent", "query": { "bool": { "must": { "range": { "parent.age": { "gte": 21 } } }, "filter": { "nested": { "path": "parent.child", "query": { "match": { "parent.child.name": "matt" } } } } } } } }, sort=[ { "parent.child.age": { "mode": "min", "order": "asc", "nested": { "path": "parent", "filter": { "range": { "parent.age": { "gte": 21 } } }, "nested": { "path": "parent.child", "filter": { "match": { "parent.child.name": "matt" } } } } } } ], ) print(resp)
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "query": { "nested": { "path": "parent", "query": { "bool": { "must": { "range": { "parent.age": { "gte": 21 } } }, "filter": { "nested": { "path": "parent.child", "query": { "match": { "parent.child.name": "matt" } } } } } } } }, "sort": [ { "parent.child.age": { "mode": "min", "order": "asc", "nested": { "path": "parent", "filter": { "range": { "parent.age": { "gte": 21 } } }, "nested": { "path": "parent.child", "filter": { "match": { "parent.child.name": "matt" } } } } } } ] }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ query: { nested: { path: "parent", query: { bool: { must: { range: { "parent.age": { gte: 21, }, }, }, filter: { nested: { path: "parent.child", query: { match: { "parent.child.name": "matt", }, }, }, }, }, }, }, }, sort: [ { "parent.child.age": { mode: "min", order: "asc", nested: { path: "parent", filter: { range: { "parent.age": { gte: 21, }, }, }, nested: { path: "parent.child", filter: { match: { "parent.child.name": "matt", }, }, }, }, }, }, ], }); console.log(response);
POST /_search { "query": { "nested": { "path": "parent", "query": { "bool": { "must": {"range": {"parent.age": {"gte": 21}}}, "filter": { "nested": { "path": "parent.child", "query": {"match": {"parent.child.name": "matt"}} } } } } } }, "sort" : [ { "parent.child.age" : { "mode" : "min", "order" : "asc", "nested": { "path": "parent", "filter": { "range": {"parent.age": {"gte": 21}} }, "nested": { "path": "parent.child", "filter": { "match": {"parent.child.name": "matt"} } } } } } ] }
按脚本和按地理距离排序时也支持嵌套排序。
缺失值
编辑missing
参数指定应如何处理缺少排序字段的文档:可以将 missing
值设置为 _last
、_first
或自定义值(将用作缺少文档的排序值)。默认值为 _last
。
例如
resp = client.search( sort=[ { "price": { "missing": "_last" } } ], query={ "term": { "product": "chocolate" } }, ) print(resp)
response = client.search( body: { sort: [ { price: { missing: '_last' } } ], query: { term: { product: 'chocolate' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "sort": [ { "price": { "missing": "_last" } } ], "query": { "term": { "product": "chocolate" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ sort: [ { price: { missing: "_last", }, }, ], query: { term: { product: "chocolate", }, }, }); console.log(response);
GET /_search { "sort" : [ { "price" : {"missing" : "_last"} } ], "query" : { "term" : { "product" : "chocolate" } } }
如果嵌套的内部对象与 nested.filter
不匹配,则使用缺失值。
忽略未映射的字段
编辑默认情况下,如果某个字段没有关联的映射,则搜索请求将失败。 unmapped_type
选项允许您忽略没有映射的字段,而不是按这些字段进行排序。此参数的值用于确定要发出哪些排序值。以下是如何使用它的示例
resp = client.search( sort=[ { "price": { "unmapped_type": "long" } } ], query={ "term": { "product": "chocolate" } }, ) print(resp)
response = client.search( body: { sort: [ { price: { unmapped_type: 'long' } } ], query: { term: { product: 'chocolate' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "sort": [ { "price": { "unmapped_type": "long" } } ], "query": { "term": { "product": "chocolate" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ sort: [ { price: { unmapped_type: "long", }, }, ], query: { term: { product: "chocolate", }, }, }); console.log(response);
GET /_search { "sort" : [ { "price" : {"unmapped_type" : "long"} } ], "query" : { "term" : { "product" : "chocolate" } } }
如果查询的任何索引都没有 price
的映射,则 Elasticsearch 将像处理类型为 long
的映射一样处理它,并且此索引中的所有文档都没有此字段的值。
地理距离排序
编辑允许按 _geo_distance
排序。以下是一个示例,假设 pin.location
是 geo_point
类型的字段
resp = client.search( sort=[ { "_geo_distance": { "pin.location": [ -70, 40 ], "order": "asc", "unit": "km", "mode": "min", "distance_type": "arc", "ignore_unmapped": True } } ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( body: { sort: [ { _geo_distance: { 'pin.location' => [ -70, 40 ], order: 'asc', unit: 'km', mode: 'min', distance_type: 'arc', ignore_unmapped: true } } ], query: { term: { user: 'kimchy' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "sort": [ { "_geo_distance": { "pin.location": [ -70, 40 ], "order": "asc", "unit": "km", "mode": "min", "distance_type": "arc", "ignore_unmapped": true } } ], "query": { "term": { "user": "kimchy" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ sort: [ { _geo_distance: { "pin.location": [-70, 40], order: "asc", unit: "km", mode: "min", distance_type: "arc", ignore_unmapped: true, }, }, ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /_search { "sort" : [ { "_geo_distance" : { "pin.location" : [-70, 40], "order" : "asc", "unit" : "km", "mode" : "min", "distance_type" : "arc", "ignore_unmapped": true } } ], "query" : { "term" : { "user" : "kimchy" } } }
-
distance_type
- 如何计算距离。可以是
arc
(默认)或plane
(更快,但在长距离和靠近两极时不太准确)。 -
mode
- 如果字段有多个地理点,该怎么办。默认情况下,升序排序时会考虑最短距离,而降序排序时会考虑最长距离。支持的值为
min
、max
、median
和avg
。 -
unit
- 计算排序值时要使用的单位。默认值为
m
(米)。 -
ignore_unmapped
- 指示是否应将未映射的字段视为缺失值。将其设置为
true
等效于在字段排序中指定unmapped_type
。默认值为false
(未映射的字段会导致搜索失败)。
地理距离排序不支持可配置的缺失值:当文档没有用于距离计算的字段值时,距离将始终被认为等于 Infinity
。
提供坐标时支持以下格式
作为属性的纬度和经度
编辑resp = client.search( sort=[ { "_geo_distance": { "pin.location": { "lat": 40, "lon": -70 }, "order": "asc", "unit": "km" } } ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( body: { sort: [ { _geo_distance: { 'pin.location' => { lat: 40, lon: -70 }, order: 'asc', unit: 'km' } } ], query: { term: { user: 'kimchy' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "sort": [ { "_geo_distance": { "pin.location": { "lat": 40, "lon": -70 }, "order": "asc", "unit": "km" } } ], "query": { "term": { "user": "kimchy" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ sort: [ { _geo_distance: { "pin.location": { lat: 40, lon: -70, }, order: "asc", unit: "km", }, }, ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /_search { "sort" : [ { "_geo_distance" : { "pin.location" : { "lat" : 40, "lon" : -70 }, "order" : "asc", "unit" : "km" } } ], "query" : { "term" : { "user" : "kimchy" } } }
纬度/经度(以 WKT 字符串表示)
编辑格式为 Well-Known Text。
resp = client.search( sort=[ { "_geo_distance": { "pin.location": "POINT (-70 40)", "order": "asc", "unit": "km" } } ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( body: { sort: [ { _geo_distance: { 'pin.location' => 'POINT (-70 40)', order: 'asc', unit: 'km' } } ], query: { term: { user: 'kimchy' } } } ) puts response
const response = await client.search({ sort: [ { _geo_distance: { "pin.location": "POINT (-70 40)", order: "asc", unit: "km", }, }, ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /_search { "sort": [ { "_geo_distance": { "pin.location": "POINT (-70 40)", "order": "asc", "unit": "km" } } ], "query": { "term": { "user": "kimchy" } } }
Geohash
编辑resp = client.search( sort=[ { "_geo_distance": { "pin.location": "drm3btev3e86", "order": "asc", "unit": "km" } } ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( body: { sort: [ { _geo_distance: { 'pin.location' => 'drm3btev3e86', order: 'asc', unit: 'km' } } ], query: { term: { user: 'kimchy' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "sort": [ { "_geo_distance": { "pin.location": "drm3btev3e86", "order": "asc", "unit": "km" } } ], "query": { "term": { "user": "kimchy" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ sort: [ { _geo_distance: { "pin.location": "drm3btev3e86", order: "asc", unit: "km", }, }, ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /_search { "sort": [ { "_geo_distance": { "pin.location": "drm3btev3e86", "order": "asc", "unit": "km" } } ], "query": { "term": { "user": "kimchy" } } }
纬度/经度(以数组表示)
编辑格式为 [经度, 纬度]
,注意,此处经度/纬度的顺序是为了符合 GeoJSON 标准。
resp = client.search( sort=[ { "_geo_distance": { "pin.location": [ -70, 40 ], "order": "asc", "unit": "km" } } ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( body: { sort: [ { _geo_distance: { 'pin.location' => [ -70, 40 ], order: 'asc', unit: 'km' } } ], query: { term: { user: 'kimchy' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "sort": [ { "_geo_distance": { "pin.location": [ -70, 40 ], "order": "asc", "unit": "km" } } ], "query": { "term": { "user": "kimchy" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ sort: [ { _geo_distance: { "pin.location": [-70, 40], order: "asc", unit: "km", }, }, ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /_search { "sort": [ { "_geo_distance": { "pin.location": [ -70, 40 ], "order": "asc", "unit": "km" } } ], "query": { "term": { "user": "kimchy" } } }
多个参考点
编辑可以传递多个地理位置点,作为包含任何 geo_point
格式的数组,例如:
resp = client.search( sort=[ { "_geo_distance": { "pin.location": [ [ -70, 40 ], [ -71, 42 ] ], "order": "asc", "unit": "km" } } ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( body: { sort: [ { _geo_distance: { 'pin.location' => [ [ -70, 40 ], [ -71, 42 ] ], order: 'asc', unit: 'km' } } ], query: { term: { user: 'kimchy' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "sort": [ { "_geo_distance": { "pin.location": [ [ -70, 40 ], [ -71, 42 ] ], "order": "asc", "unit": "km" } } ], "query": { "term": { "user": "kimchy" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ sort: [ { _geo_distance: { "pin.location": [ [-70, 40], [-71, 42], ], order: "asc", unit: "km", }, }, ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /_search { "sort": [ { "_geo_distance": { "pin.location": [ [ -70, 40 ], [ -71, 42 ] ], "order": "asc", "unit": "km" } } ], "query": { "term": { "user": "kimchy" } } }
等等。
文档的最终距离将是文档中所有点到排序请求中给定所有点的 min
/max
/avg
(通过 mode
定义)距离。
基于脚本的排序
编辑允许基于自定义脚本进行排序,这是一个示例:
resp = client.search( query={ "term": { "user": "kimchy" } }, sort={ "_script": { "type": "number", "script": { "lang": "painless", "source": "doc['field_name'].value * params.factor", "params": { "factor": 1.1 } }, "order": "asc" } }, ) print(resp)
response = client.search( body: { query: { term: { user: 'kimchy' } }, sort: { _script: { type: 'number', script: { lang: 'painless', source: "doc['field_name'].value * params.factor", params: { factor: 1.1 } }, order: 'asc' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "query": { "term": { "user": "kimchy" } }, "sort": { "_script": { "type": "number", "script": { "lang": "painless", "source": "doc['field_name'].value * params.factor", "params": { "factor": 1.1 } }, "order": "asc" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ query: { term: { user: "kimchy", }, }, sort: { _script: { type: "number", script: { lang: "painless", source: "doc['field_name'].value * params.factor", params: { factor: 1.1, }, }, order: "asc", }, }, }); console.log(response);
GET /_search { "query": { "term": { "user": "kimchy" } }, "sort": { "_script": { "type": "number", "script": { "lang": "painless", "source": "doc['field_name'].value * params.factor", "params": { "factor": 1.1 } }, "order": "asc" } } }
跟踪得分
编辑当对字段进行排序时,不会计算得分。通过将 track_scores
设置为 true,仍然会计算并跟踪得分。
resp = client.search( track_scores=True, sort=[ { "post_date": { "order": "desc" } }, { "name": "desc" }, { "age": "desc" } ], query={ "term": { "user": "kimchy" } }, ) print(resp)
response = client.search( body: { track_scores: true, sort: [ { post_date: { order: 'desc' } }, { name: 'desc' }, { age: 'desc' } ], query: { term: { user: 'kimchy' } } } ) puts response
res, err := es.Search( es.Search.WithBody(strings.NewReader(`{ "track_scores": true, "sort": [ { "post_date": { "order": "desc" } }, { "name": "desc" }, { "age": "desc" } ], "query": { "term": { "user": "kimchy" } } }`)), es.Search.WithPretty(), ) fmt.Println(res, err)
const response = await client.search({ track_scores: true, sort: [ { post_date: { order: "desc", }, }, { name: "desc", }, { age: "desc", }, ], query: { term: { user: "kimchy", }, }, }); console.log(response);
GET /_search { "track_scores": true, "sort" : [ { "post_date" : {"order" : "desc"} }, { "name" : "desc" }, { "age" : "desc" } ], "query" : { "term" : { "user" : "kimchy" } } }
内存注意事项
编辑排序时,相关的排序字段值会加载到内存中。这意味着每个分片应该有足够的内存来容纳它们。对于基于字符串的类型,排序的字段不应该被分析/分词。对于数字类型,如果可能,建议将类型显式设置为更窄的类型(如 short
、integer
和 float
)。