123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634 |
- [[sort-search-results]]
- == Sort search results
- Allows you to add one or more sorts on specific fields. Each sort can be
- reversed as well. The sort is defined on a per field level, with special
- field name for `_score` to sort by score, and `_doc` to sort by index order.
- Assuming the following index mapping:
- [source,console]
- --------------------------------------------------
- PUT /my-index-000001
- {
- "mappings": {
- "properties": {
- "post_date": { "type": "date" },
- "user": {
- "type": "keyword"
- },
- "name": {
- "type": "keyword"
- },
- "age": { "type": "integer" }
- }
- }
- }
- --------------------------------------------------
- [source,console]
- --------------------------------------------------
- GET /my-index-000001/_search
- {
- "sort" : [
- { "post_date" : {"order" : "asc"}},
- "user",
- { "name" : "desc" },
- { "age" : "desc" },
- "_score"
- ],
- "query" : {
- "term" : { "user" : "kimchy" }
- }
- }
- --------------------------------------------------
- // TEST[continued]
- NOTE: `_doc` has no real use-case besides being the most efficient sort order.
- So if you don't care about the order in which documents are returned, then you
- should sort by `_doc`. This especially helps when <<request-body-search-scroll,scrolling>>.
- [discrete]
- === Sort Values
- The sort values for each document returned are also returned as part of
- the response.
- [discrete]
- === Sort Order
- The `order` option can have the following values:
- [horizontal]
- `asc`:: Sort in ascending order
- `desc`:: Sort in descending order
- The order defaults to `desc` when sorting on the `_score`, and defaults
- to `asc` when sorting on anything else.
- [discrete]
- === Sort mode option
- Elasticsearch supports sorting by array or multi-valued fields. The `mode` option
- controls what array value is picked for sorting the document it belongs
- to. The `mode` option can have the following values:
- [horizontal]
- `min`:: Pick the lowest value.
- `max`:: Pick the highest value.
- `sum`:: Use the sum of all values as sort value. Only applicable for
- number based array fields.
- `avg`:: Use the average of all values as sort value. Only applicable
- for number based array fields.
- `median`:: Use the median of all values as sort value. Only applicable
- for number based array fields.
- The default sort mode in the ascending sort order is `min` -- the lowest value
- is picked. The default sort mode in the descending order is `max` --
- the highest value is picked.
- [discrete]
- ==== Sort mode example usage
- In the example below the field price has multiple prices per document.
- In this case the result hits will be sorted by price ascending based on
- the average price per document.
- [source,console]
- --------------------------------------------------
- PUT /my-index-000001/_doc/1?refresh
- {
- "product": "chocolate",
- "price": [20, 4]
- }
- POST /_search
- {
- "query" : {
- "term" : { "product" : "chocolate" }
- },
- "sort" : [
- {"price" : {"order" : "asc", "mode" : "avg"}}
- ]
- }
- --------------------------------------------------
- [discrete]
- === Sorting numeric fields
- For numeric fields it is also possible to cast the values from one type
- to another using the `numeric_type` option.
- This option accepts the following values: [`"double", "long", "date", "date_nanos"`]
- and can be useful for searches across multiple data streams or indices where the sort field is mapped differently.
- Consider for instance these two indices:
- [source,console]
- --------------------------------------------------
- PUT /index_double
- {
- "mappings": {
- "properties": {
- "field": { "type": "double" }
- }
- }
- }
- --------------------------------------------------
- [source,console]
- --------------------------------------------------
- PUT /index_long
- {
- "mappings": {
- "properties": {
- "field": { "type": "long" }
- }
- }
- }
- --------------------------------------------------
- // TEST[continued]
- Since `field` is mapped as a `double` in the first index and as a `long`
- in the second index, it is not possible to use this field to sort requests
- that query both indices by default. However you can force the type to one
- or the other with the `numeric_type` option in order to force a specific
- type for all indices:
- [source,console]
- --------------------------------------------------
- POST /index_long,index_double/_search
- {
- "sort" : [
- {
- "field" : {
- "numeric_type" : "double"
- }
- }
- ]
- }
- --------------------------------------------------
- // TEST[continued]
- In the example above, values for the `index_long` index are casted to
- a double in order to be compatible with the values produced by the
- `index_double` index.
- It is also possible to transform a floating point field into a `long`
- but note that in this case floating points are replaced by the largest
- value that is less than or equal (greater than or equal if the value
- is negative) to the argument and is equal to a mathematical integer.
- This option can also be used to convert a `date` field that uses millisecond
- resolution to a `date_nanos` field with nanosecond resolution.
- Consider for instance these two indices:
- [source,console]
- --------------------------------------------------
- PUT /index_double
- {
- "mappings": {
- "properties": {
- "field": { "type": "date" }
- }
- }
- }
- --------------------------------------------------
- [source,console]
- --------------------------------------------------
- PUT /index_long
- {
- "mappings": {
- "properties": {
- "field": { "type": "date_nanos" }
- }
- }
- }
- --------------------------------------------------
- // TEST[continued]
- Values in these indices are stored with different resolutions so sorting on these
- fields will always sort the `date` before the `date_nanos` (ascending order).
- With the `numeric_type` type option it is possible to set a single resolution for
- the sort, setting to `date` will convert the `date_nanos` to the millisecond resolution
- while `date_nanos` will convert the values in the `date` field to the nanoseconds resolution:
- [source,console]
- --------------------------------------------------
- POST /index_long,index_double/_search
- {
- "sort" : [
- {
- "field" : {
- "numeric_type" : "date_nanos"
- }
- }
- ]
- }
- --------------------------------------------------
- // TEST[continued]
- [WARNING]
- To avoid overflow, the conversion to `date_nanos` cannot be applied on dates before
- 1970 and after 2262 as nanoseconds are represented as longs.
- [discrete]
- [[nested-sorting]]
- === Sorting within nested objects.
- Elasticsearch also supports sorting by
- fields that are inside one or more nested objects. The sorting by nested
- field support has a `nested` sort option with the following properties:
- `path`::
- Defines on which nested object to sort. The actual
- sort field must be a direct field inside this nested object.
- When sorting by nested field, this field is mandatory.
- `filter`::
- A filter that the inner objects inside the nested path
- should match with in order for its field values to be taken into account
- by sorting. Common case is to repeat the query / filter inside the
- nested filter or query. By default no `filter` is active.
- `max_children`::
- The maximum number of children to consider per root document
- when picking the sort value. Defaults to unlimited.
- `nested`::
- Same as top-level `nested` but applies to another nested path within the
- current nested object.
- NOTE: Elasticsearch will throw an error if a nested field is defined in a sort without
- a `nested` context.
- [discrete]
- ==== Nested sorting examples
- In the below example `offer` is a field of type `nested`.
- The nested `path` needs to be specified; otherwise, Elasticsearch doesn't know on what nested level sort values need to be captured.
- [source,console]
- --------------------------------------------------
- POST /_search
- {
- "query" : {
- "term" : { "product" : "chocolate" }
- },
- "sort" : [
- {
- "offer.price" : {
- "mode" : "avg",
- "order" : "asc",
- "nested": {
- "path": "offer",
- "filter": {
- "term" : { "offer.color" : "blue" }
- }
- }
- }
- }
- ]
- }
- --------------------------------------------------
- In the below example `parent` and `child` fields are of type `nested`.
- The `nested.path` needs to be specified at each level; otherwise, Elasticsearch doesn't know on what nested level sort values need to be captured.
- [source,console]
- --------------------------------------------------
- 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"}
- }
- }
- }
- }
- }
- ]
- }
- --------------------------------------------------
- Nested sorting is also supported when sorting by
- scripts and sorting by geo distance.
- [discrete]
- === Missing Values
- The `missing` parameter specifies how docs which are missing
- the sort field should be treated: The `missing` value can be
- set to `_last`, `_first`, or a custom value (that
- will be used for missing docs as the sort value).
- The default is `_last`.
- For example:
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "sort" : [
- { "price" : {"missing" : "_last"} }
- ],
- "query" : {
- "term" : { "product" : "chocolate" }
- }
- }
- --------------------------------------------------
- NOTE: If a nested inner object doesn't match with
- the `nested.filter` then a missing value is used.
- [discrete]
- === Ignoring Unmapped Fields
- By default, the search request will fail if there is no mapping
- associated with a field. The `unmapped_type` option allows you to ignore
- fields that have no mapping and not sort by them. The value of this
- parameter is used to determine what sort values to emit. Here is an
- example of how it can be used:
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "sort" : [
- { "price" : {"unmapped_type" : "long"} }
- ],
- "query" : {
- "term" : { "product" : "chocolate" }
- }
- }
- --------------------------------------------------
- If any of the indices that are queried doesn't have a mapping for `price`
- then Elasticsearch will handle it as if there was a mapping of type
- `long`, with all documents in this index having no value for this field.
- [discrete]
- [[geo-sorting]]
- === Geo Distance Sorting
- Allow to sort by `_geo_distance`. Here is an example, assuming `pin.location` is a field of type `geo_point`:
- [source,console]
- --------------------------------------------------
- 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`::
- How to compute the distance. Can either be `arc` (default), or `plane` (faster, but inaccurate on long distances and close to the poles).
- `mode`::
- What to do in case a field has several geo points. By default, the shortest
- distance is taken into account when sorting in ascending order and the
- longest distance when sorting in descending order. Supported values are
- `min`, `max`, `median` and `avg`.
- `unit`::
- The unit to use when computing sort values. The default is `m` (meters).
- `ignore_unmapped`::
- Indicates if the unmapped field should be treated as a missing value. Setting it to `true` is equivalent to specifying
- an `unmapped_type` in the field sort. The default is `false` (unmapped field cause the search to fail).
- NOTE: geo distance sorting does not support configurable missing values: the
- distance will always be considered equal to +Infinity+ when a document does not
- have values for the field that is used for distance computation.
- The following formats are supported in providing the coordinates:
- [discrete]
- ==== Lat Lon as Properties
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "sort" : [
- {
- "_geo_distance" : {
- "pin.location" : {
- "lat" : 40,
- "lon" : -70
- },
- "order" : "asc",
- "unit" : "km"
- }
- }
- ],
- "query" : {
- "term" : { "user" : "kimchy" }
- }
- }
- --------------------------------------------------
- [discrete]
- ==== Lat Lon as String
- Format in `lat,lon`.
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "sort": [
- {
- "_geo_distance": {
- "pin.location": "40,-70",
- "order": "asc",
- "unit": "km"
- }
- }
- ],
- "query": {
- "term": { "user": "kimchy" }
- }
- }
- --------------------------------------------------
- [discrete]
- ==== Geohash
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "sort": [
- {
- "_geo_distance": {
- "pin.location": "drm3btev3e86",
- "order": "asc",
- "unit": "km"
- }
- }
- ],
- "query": {
- "term": { "user": "kimchy" }
- }
- }
- --------------------------------------------------
- [discrete]
- ==== Lat Lon as Array
- Format in `[lon, lat]`, note, the order of lon/lat here in order to
- conform with http://geojson.org/[GeoJSON].
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "sort": [
- {
- "_geo_distance": {
- "pin.location": [ -70, 40 ],
- "order": "asc",
- "unit": "km"
- }
- }
- ],
- "query": {
- "term": { "user": "kimchy" }
- }
- }
- --------------------------------------------------
- [discrete]
- === Multiple reference points
- Multiple geo points can be passed as an array containing any `geo_point` format, for example
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "sort": [
- {
- "_geo_distance": {
- "pin.location": [ [ -70, 40 ], [ -71, 42 ] ],
- "order": "asc",
- "unit": "km"
- }
- }
- ],
- "query": {
- "term": { "user": "kimchy" }
- }
- }
- --------------------------------------------------
- and so forth.
- The final distance for a document will then be `min`/`max`/`avg` (defined via `mode`) distance of all points contained in the document to all points given in the sort request.
- [discrete]
- === Script Based Sorting
- Allow to sort based on custom scripts, here is an example:
- [source,console]
- --------------------------------------------------
- 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"
- }
- }
- }
- --------------------------------------------------
- [discrete]
- === Track Scores
- When sorting on a field, scores are not computed. By setting
- `track_scores` to true, scores will still be computed and tracked.
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "track_scores": true,
- "sort" : [
- { "post_date" : {"order" : "desc"} },
- { "name" : "desc" },
- { "age" : "desc" }
- ],
- "query" : {
- "term" : { "user" : "kimchy" }
- }
- }
- --------------------------------------------------
- [discrete]
- === Memory Considerations
- When sorting, the relevant sorted field values are loaded into memory.
- This means that per shard, there should be enough memory to contain
- them. For string based types, the field sorted on should not be analyzed
- / tokenized. For numeric types, if possible, it is recommended to
- explicitly set the type to narrower types (like `short`, `integer` and
- `float`).
|