script-score-query.asciidoc 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  1. [[query-dsl-script-score-query]]
  2. === Script Score Query
  3. experimental[]
  4. The `script_score` allows you to modify the score of documents that are
  5. retrieved by a query. This can be useful if, for example, a score
  6. function is computationally expensive and it is sufficient to compute
  7. the score on a filtered set of documents.
  8. To use `script_score`, you have to define a query and a script -
  9. a function to be used to compute a new score for each document returned
  10. by the query. For more information on scripting see
  11. <<modules-scripting, scripting documentation>>.
  12. Here is an example of using `script_score` to assign each matched document
  13. a score equal to the number of likes divided by 10:
  14. [source,js]
  15. --------------------------------------------------
  16. GET /_search
  17. {
  18. "query" : {
  19. "script_score" : {
  20. "query" : {
  21. "match": { "message": "elasticsearch" }
  22. },
  23. "script" : {
  24. "source" : "doc['likes'].value / 10 "
  25. }
  26. }
  27. }
  28. }
  29. --------------------------------------------------
  30. // CONSOLE
  31. // TEST[setup:twitter]
  32. ==== Accessing the score of a document within a script
  33. Within a script, you can
  34. <<modules-scripting-fields#scripting-score, access>>
  35. the `_score` variable which represents the current relevance score of a
  36. document.
  37. ==== Predefined functions within a Painless script
  38. You can use any of the available
  39. <<painless-api-reference, painless functions>> in the painless script.
  40. Besides these functions, there are a number of predefined functions
  41. that can help you with scoring. We suggest you to use them instead of
  42. rewriting equivalent functions of your own, as these functions try
  43. to be the most efficient by using the internal mechanisms.
  44. ===== rational
  45. latexmath:[rational(value,k) = value/(k + value)]
  46. [source,js]
  47. --------------------------------------------------
  48. "script" : {
  49. "source" : "rational(doc['likes'].value, 1)"
  50. }
  51. --------------------------------------------------
  52. // NOTCONSOLE
  53. ===== sigmoid
  54. latexmath:[sigmoid(value, k, a) = value^a/ (k^a + value^a)]
  55. [source,js]
  56. --------------------------------------------------
  57. "script" : {
  58. "source" : "sigmoid(doc['likes'].value, 2, 1)"
  59. }
  60. --------------------------------------------------
  61. // NOTCONSOLE
  62. [[random-functions]]
  63. ===== Random functions
  64. There are two predefined ways to produce random values:
  65. 1. `randomNotReproducible()` uses `java.util.Random` class
  66. to generate a random value of the type `long`.
  67. The generated values are not reproducible between requests' invocations.
  68. [source,js]
  69. --------------------------------------------------
  70. "script" : {
  71. "source" : "randomNotReproducible()"
  72. }
  73. --------------------------------------------------
  74. // NOTCONSOLE
  75. 2. `randomReproducible(String seedValue, int seed)` produces
  76. reproducible random values of type `long`. This function requires
  77. more computational time and memory than the non-reproducible version.
  78. A good candidate for the `seedValue` is document field values that
  79. are unique across documents and already pre-calculated and preloaded
  80. in the memory. For example, values of the document's `_seq_no` field
  81. is a good candidate, as documents on the same shard have unique values
  82. for the `_seq_no` field.
  83. [source,js]
  84. --------------------------------------------------
  85. "script" : {
  86. "source" : "randomReproducible(Long.toString(doc['_seq_no'].value), 100)"
  87. }
  88. --------------------------------------------------
  89. // NOTCONSOLE
  90. A drawback of using `_seq_no` is that generated values change if
  91. documents are updated. Another drawback is not absolute uniqueness, as
  92. documents from different shards with the same sequence numbers
  93. generate the same random values.
  94. If you need random values to be distinct across different shards,
  95. you can use a field with unique values across shards,
  96. such as `_id`, but watch out for the memory usage as all
  97. these unique values need to be loaded into memory.
  98. [source,js]
  99. --------------------------------------------------
  100. "script" : {
  101. "source" : "randomReproducible(doc['_id'].value, 100)"
  102. }
  103. --------------------------------------------------
  104. // NOTCONSOLE
  105. [[decay-functions]]
  106. ===== Decay functions for numeric fields
  107. You can read more about decay functions
  108. <<query-dsl-function-score-query#function-decay, here>>.
  109. * `double decayNumericLinear(double origin, double scale, double offset, double decay, double docValue)`
  110. * `double decayNumericExp(double origin, double scale, double offset, double decay, double docValue)`
  111. * `double decayNumericGauss(double origin, double scale, double offset, double decay, double docValue)`
  112. [source,js]
  113. --------------------------------------------------
  114. "script" : {
  115. "source" : "decayNumericLinear(params.origin, params.scale, params.offset, params.decay, doc['dval'].value)",
  116. "params": { <1>
  117. "origin": 20,
  118. "scale": 10,
  119. "decay" : 0.5,
  120. "offset" : 0
  121. }
  122. }
  123. --------------------------------------------------
  124. // NOTCONSOLE
  125. <1> Use `params` to compile a script only once for different values of parameters
  126. ===== Decay functions for geo fields
  127. * `double decayGeoLinear(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)`
  128. * `double decayGeoExp(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)`
  129. * `double decayGeoGauss(String originStr, String scaleStr, String offsetStr, double decay, GeoPoint docValue)`
  130. [source,js]
  131. --------------------------------------------------
  132. "script" : {
  133. "source" : "decayGeoExp(params.origin, params.scale, params.offset, params.decay, doc['location'].value)",
  134. "params": {
  135. "origin": "40, -70.12",
  136. "scale": "200km",
  137. "offset": "0km",
  138. "decay" : 0.2
  139. }
  140. }
  141. --------------------------------------------------
  142. // NOTCONSOLE
  143. ===== Decay functions for date fields
  144. * `double decayDateLinear(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)`
  145. * `double decayDateExp(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)`
  146. * `double decayDateGauss(String originStr, String scaleStr, String offsetStr, double decay, JodaCompatibleZonedDateTime docValueDate)`
  147. [source,js]
  148. --------------------------------------------------
  149. "script" : {
  150. "source" : "decayDateGauss(params.origin, params.scale, params.offset, params.decay, doc['date'].value)",
  151. "params": {
  152. "origin": "2008-01-01T01:00:00Z",
  153. "scale": "1h",
  154. "offset" : "0",
  155. "decay" : 0.5
  156. }
  157. }
  158. --------------------------------------------------
  159. // NOTCONSOLE
  160. NOTE: Decay functions on dates are limited to dates in the default format
  161. and default time zone. Also calculations with `now` are not supported.
  162. ==== Faster alternatives
  163. Script Score Query calculates the score for every hit (matching document).
  164. There are faster alternative query types that can efficiently skip
  165. non-competitive hits:
  166. * If you want to boost documents on some static fields, use
  167. <<query-dsl-feature-query, Feature Query>>.
  168. ==== Transition from Function Score Query
  169. We are deprecating <<query-dsl-function-score-query, Function Score>>, and
  170. Script Score Query will be a substitute for it.
  171. Here we describe how Function Score Query's functions can be
  172. equivalently implemented in Script Score Query:
  173. ===== `script_score`
  174. What you used in `script_score` of the Function Score query, you
  175. can copy into the Script Score query. No changes here.
  176. ===== `weight`
  177. `weight` function can be implemented in the Script Score query through
  178. the following script:
  179. [source,js]
  180. --------------------------------------------------
  181. "script" : {
  182. "source" : "params.weight * _score",
  183. "params": {
  184. "weight": 2
  185. }
  186. }
  187. --------------------------------------------------
  188. // NOTCONSOLE
  189. ===== `random_score`
  190. Use `randomReproducible` and `randomNotReproducible` functions
  191. as described in <<random-functions, random functions>>.
  192. ===== `field_value_factor`
  193. `field_value_factor` function can be easily implemented through script:
  194. [source,js]
  195. --------------------------------------------------
  196. "script" : {
  197. "source" : "Math.log10(doc['field'].value * params.factor)",
  198. params" : {
  199. "factor" : 5
  200. }
  201. }
  202. --------------------------------------------------
  203. // NOTCONSOLE
  204. For checking if a document has a missing value, you can use
  205. `doc['field'].size() == 0`. For example, this script will use
  206. a value `1` if a document doesn't have a field `field`:
  207. [source,js]
  208. --------------------------------------------------
  209. "script" : {
  210. "source" : "Math.log10((doc['field'].size() == 0 ? 1 : doc['field'].value()) * params.factor)",
  211. params" : {
  212. "factor" : 5
  213. }
  214. }
  215. --------------------------------------------------
  216. // NOTCONSOLE
  217. This table lists how `field_value_factor` modifiers can be implemented
  218. through a script:
  219. [cols="<,<",options="header",]
  220. |=======================================================================
  221. | Modifier | Implementation in Script Score
  222. | `none` | -
  223. | `log` | `Math.log10(doc['f'].value)`
  224. | `log1p` | `Math.log10(doc['f'].value + 1)`
  225. | `log2p` | `Math.log10(doc['f'].value + 2)`
  226. | `ln` | `Math.log(doc['f'].value)`
  227. | `ln1p` | `Math.log(doc['f'].value + 1)`
  228. | `ln2p` | `Math.log(doc['f'].value + 2)`
  229. | `square` | `Math.pow(doc['f'].value, 2)`
  230. | `sqrt` | `Math.sqrt(doc['f'].value)`
  231. | `reciprocal` | `1.0 / doc['f'].value`
  232. |=======================================================================
  233. ===== `decay functions`
  234. Script Score query has equivalent <<decay-functions, decay functions>>
  235. that can be used in script.