123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331 |
- [[query-dsl-script-score-query]]
- === Script score query
- ++++
- <titleabbrev>Script score</titleabbrev>
- ++++
- Uses a <<modules-scripting,script>> to provide a custom score for returned
- documents.
- The `script_score` query is useful if, for example, a scoring function is expensive and you only need to calculate the score of a filtered set of documents.
- [[script-score-query-ex-request]]
- ==== Example request
- The following `script_score` query assigns each returned document a score equal to the `likes` field value divided by `10`.
- [source,console]
- --------------------------------------------------
- GET /_search
- {
- "query" : {
- "script_score" : {
- "query" : {
- "match": { "message": "elasticsearch" }
- },
- "script" : {
- "source" : "doc['likes'].value / 10 "
- }
- }
- }
- }
- --------------------------------------------------
- [[script-score-top-level-params]]
- ==== Top-level parameters for `script_score`
- `query`::
- (Required, query object) Query used to return documents.
- `script`::
- +
- --
- (Required, <<modules-scripting-using,script object>>) Script used to compute the score of documents returned by the `query`.
- IMPORTANT: Final relevance scores from the `script_score` query cannot be
- negative. To support certain search optimizations, Lucene requires
- scores be positive or `0`.
- --
- `min_score`::
- (Optional, float) Documents with a <<relevance-scores,relevance score>> lower
- than this floating point number are excluded from the search results.
- [[script-score-query-notes]]
- ==== Notes
- [[script-score-access-scores]]
- ===== Use relevance scores in a script
- Within a script, you can
- {ref}/modules-scripting-fields.html#scripting-score[access]
- the `_score` variable which represents the current relevance score of a
- document.
- [[script-score-predefined-functions]]
- ===== Predefined functions
- You can use any of the available {painless}/painless-contexts.html[painless
- functions] in your `script`. You can also use the following predefined functions
- to customize scoring:
- * <<script-score-saturation>>
- * <<script-score-sigmoid>>
- * <<random-score-function>>
- * <<decay-functions-numeric-fields>>
- * <<decay-functions-geo-fields>>
- * <<decay-functions-date-fields>>
- * <<script-score-functions-vector-fields>>
- We suggest using these predefined functions instead of writing your own.
- These functions take advantage of efficiencies from {es}' internal mechanisms.
- [[script-score-saturation]]
- ====== Saturation
- `saturation(value,k) = value/(k + value)`
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "saturation(doc['likes'].value, 1)"
- }
- --------------------------------------------------
- // NOTCONSOLE
- [[script-score-sigmoid]]
- ====== Sigmoid
- `sigmoid(value, k, a) = value^a/ (k^a + value^a)`
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "sigmoid(doc['likes'].value, 2, 1)"
- }
- --------------------------------------------------
- // NOTCONSOLE
- [[random-score-function]]
- ====== Random score function
- `random_score` function generates scores that are uniformly distributed
- from 0 up to but not including 1.
- `randomScore` function has the following syntax:
- `randomScore(<seed>, <fieldName>)`.
- It has a required parameter - `seed` as an integer value,
- and an optional parameter - `fieldName` as a string value.
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "randomScore(100, '_seq_no')"
- }
- --------------------------------------------------
- // NOTCONSOLE
- If the `fieldName` parameter is omitted, the internal Lucene
- document ids will be used as a source of randomness. This is very efficient,
- but unfortunately not reproducible since documents might be renumbered
- by merges.
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "randomScore(100)"
- }
- --------------------------------------------------
- // NOTCONSOLE
- Note that documents that are within the same shard and have the
- same value for field will get the same score, so it is usually desirable
- to use a field that has unique values for all documents across a shard.
- A good default choice might be to use the `_seq_no`
- field, whose only drawback is that scores will change if the document is
- updated since update operations also update the value of the `_seq_no` field.
- [[decay-functions-numeric-fields]]
- ====== Decay functions for numeric fields
- You can read more about decay functions
- {ref}/query-dsl-function-score-query.html#function-decay[here].
- * `double decayNumericLinear(double origin, double scale, double offset, double decay, double docValue)`
- * `double decayNumericExp(double origin, double scale, double offset, double decay, double docValue)`
- * `double decayNumericGauss(double origin, double scale, double offset, double decay, double docValue)`
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['dval'].value)",
- "params": { <1>
- "origin": 20,
- "scale": 10,
- "decay" : 0.5,
- "offset" : 0
- }
- }
- --------------------------------------------------
- // NOTCONSOLE
- <1> Using `params` allows to compile the script only once, even if params change.
- [[decay-functions-geo-fields]]
- ====== Decay functions for geo fields
- * `double decayGeoLinear(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)`
- * `double decayGeoExp(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)`
- * `double decayGeoGauss(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)`
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "decayGeoExp(params.origin, params.scale, params.offset, params.decay, doc['location'].value)",
- "params": {
- "origin": "40, -70.12",
- "scale": "200km",
- "offset": "0km",
- "decay" : 0.2
- }
- }
- --------------------------------------------------
- // NOTCONSOLE
- [[decay-functions-date-fields]]
- ====== Decay functions for date fields
- * `double decayDateLinear(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)`
- * `double decayDateExp(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)`
- * `double decayDateGauss(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)`
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "decayDateGauss(params.origin, params.scale, params.offset, params.decay, doc['date'].value)",
- "params": {
- "origin": "2008-01-01T01:00:00Z",
- "scale": "1h",
- "offset" : "0",
- "decay" : 0.5
- }
- }
- --------------------------------------------------
- // NOTCONSOLE
- NOTE: Decay functions on dates are limited to dates in the default format
- and default time zone. Also calculations with `now` are not supported.
- [[script-score-functions-vector-fields]]
- ====== Functions for vector fields
- <<vector-functions, Functions for vector fields>> are accessible through
- `script_score` query.
- [[script-score-faster-alt]]
- ===== Faster alternatives
- The `script_score` query calculates the score for
- every matching document, or hit. There are faster alternative query types that
- can efficiently skip non-competitive hits:
- * If you want to boost documents on some static fields, use the
- <<query-dsl-rank-feature-query, `rank_feature`>> query.
- * If you want to boost documents closer to a date or geographic point, use the
- <<query-dsl-distance-feature-query, `distance_feature`>> query.
- [[script-score-function-score-transition]]
- ===== Transition from the function score query
- We are deprecating the <<query-dsl-function-score-query, `function_score`>>
- query. We recommend using the `script_score` query instead.
- You can implement the following functions from the `function_score` query using
- the `script_score` query:
- * <<script-score>>
- * <<weight>>
- * <<random-score>>
- * <<field-value-factor>>
- * <<decay-functions>>
- [[script-score]]
- ====== `script_score`
- What you used in `script_score` of the Function Score query, you
- can copy into the Script Score query. No changes here.
- [[weight]]
- ====== `weight`
- `weight` function can be implemented in the Script Score query through
- the following script:
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "params.weight * _score",
- "params": {
- "weight": 2
- }
- }
- --------------------------------------------------
- // NOTCONSOLE
- [[random-score]]
- ====== `random_score`
- Use `randomScore` function
- as described in <<random-score-function, random score function>>.
- [[field-value-factor]]
- ====== `field_value_factor`
- `field_value_factor` function can be easily implemented through script:
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "Math.log10(doc['field'].value * params.factor)",
- params" : {
- "factor" : 5
- }
- }
- --------------------------------------------------
- // NOTCONSOLE
- For checking if a document has a missing value, you can use
- `doc['field'].size() == 0`. For example, this script will use
- a value `1` if a document doesn't have a field `field`:
- [source,js]
- --------------------------------------------------
- "script" : {
- "source" : "Math.log10((doc['field'].size() == 0 ? 1 : doc['field'].value()) * params.factor)",
- params" : {
- "factor" : 5
- }
- }
- --------------------------------------------------
- // NOTCONSOLE
- This table lists how `field_value_factor` modifiers can be implemented
- through a script:
- [cols="<,<",options="header",]
- |=======================================================================
- | Modifier | Implementation in Script Score
- | `none` | -
- | `log` | `Math.log10(doc['f'].value)`
- | `log1p` | `Math.log10(doc['f'].value + 1)`
- | `log2p` | `Math.log10(doc['f'].value + 2)`
- | `ln` | `Math.log(doc['f'].value)`
- | `ln1p` | `Math.log(doc['f'].value + 1)`
- | `ln2p` | `Math.log(doc['f'].value + 2)`
- | `square` | `Math.pow(doc['f'].value, 2)`
- | `sqrt` | `Math.sqrt(doc['f'].value)`
- | `reciprocal` | `1.0 / doc['f'].value`
- |=======================================================================
- [[decay-functions]]
- ====== `decay` functions
- The `script_score` query has equivalent <<decay-functions, decay functions>>
- that can be used in script.
- include::{es-repo-dir}/vectors/vector-functions.asciidoc[]
|