OpenSearch/docs/reference/modules/scripting/fields.asciidoc

239 lines
7.0 KiB
Plaintext
Raw Normal View History

[[modules-scripting-fields]]
=== Accessing document fields and special variables
Depending on where a script is used, it will have access to certain special
variables and document fields.
[float]
== Update scripts
A script used in the <<docs-update,update>>,
<<docs-update-by-query,update-by-query>>, or <<docs-reindex,reindex>>
API will have access to the `ctx` variable which exposes:
[horizontal]
`ctx._source`:: Access to the document <<mapping-source-field,`_source` field>>.
`ctx.op`:: The operation that should be applied to the document: `index` or `delete`.
`ctx._index` etc:: Access to <<mapping-fields,document meta-fields>>, some of which may be read-only.
[float]
== Search and Aggregation scripts
With the exception of <<search-request-script-fields,script fields>> which are
executed once per search hit, scripts used in search and aggregations will be
executed once for every document which might match a query or an aggregation.
Depending on how many documents you have, this could mean millions or billions
of executions: these scripts need to be fast!
Field values can be accessed from a script using
<<modules-scripting-doc-vals,doc-values>>, or
<<modules-scripting-stored,stored fields or `_source` field>>, which are explained below.
[[scripting-score]]
[float]
=== Accessing the score of a document within a script
Scripts used in the <<query-dsl-function-score-query,`function_score` query>>,
in <<search-request-sort,script-based sorting>>, or in
<<search-aggregations,aggregations>> have access to the `_score` variable which
represents the current relevance score of a document.
Here's an example of using a script in a
<<query-dsl-function-score-query,`function_score` query>> to alter the
relevance `_score` of each document:
[source,js]
-------------------------------------
PUT my_index/_doc/1?refresh
{
"text": "quick brown fox",
"popularity": 1
}
PUT my_index/_doc/2?refresh
{
"text": "quick fox",
"popularity": 5
}
GET my_index/_search
{
"query": {
"function_score": {
"query": {
"match": {
"text": "quick brown fox"
}
},
"script_score": {
"script": {
"lang": "expression",
"source": "_score * doc['popularity']"
}
}
}
}
}
-------------------------------------
// CONSOLE
[float]
[[modules-scripting-doc-vals]]
=== Doc Values
By far the fastest most efficient way to access a field value from a
script is to use the `doc['field_name']` syntax, which retrieves the field
value from <<doc-values,doc values>>. Doc values are a columnar field value
store, enabled by default on all fields except for <<text,analyzed `text` fields>>.
[source,js]
-------------------------------
PUT my_index/_doc/1?refresh
{
"cost_price": 100
}
GET my_index/_search
{
"script_fields": {
"sales_price": {
"script": {
"lang": "expression",
"source": "doc['cost_price'] * markup",
"params": {
"markup": 0.2
}
}
}
}
}
-------------------------------
// CONSOLE
Doc-values can only return "simple" field values like numbers, dates, geo-
points, terms, etc, or arrays of these values if the field is multi-valued.
It cannot return JSON objects.
[NOTE]
.Missing fields
===================================================
The `doc['field']` will throw an error if `field` is missing from the mappings.
In `painless`, a check can first be done with `doc.containsKey('field')` to guard
accessing the `doc` map. Unfortunately, there is no way to check for the
existence of the field in mappings in an `expression` script.
===================================================
[NOTE]
.Doc values and `text` fields
===================================================
The `doc['field']` syntax can also be used for <<text,analyzed `text` fields>>
if <<fielddata,`fielddata`>> is enabled, but *BEWARE*: enabling fielddata on a
`text` field requires loading all of the terms into the JVM heap, which can be
very expensive both in terms of memory and CPU. It seldom makes sense to
access `text` fields from scripts.
===================================================
[float]
[[modules-scripting-stored]]
=== Stored Fields and `_source`
_Stored fields_ -- fields explicitly marked as
<<mapping-store,`"store": true`>> -- can be accessed using the
`_fields['field_name'].value` or `_fields['field_name']` syntax.
The document <<mapping-source-field,`_source`>>, which is really just a
special stored field, can be accessed using the `_source.field_name` syntax.
The `_source` is loaded as a map-of-maps, so properties within object fields
can be accessed as, for example, `_source.name.first`.
[IMPORTANT]
.Prefer doc-values to stored fields
=========================================================
Stored fields (which includes the stored `_source` field) are much slower than
doc-values. They are optimised for returning several fields per result,
while doc values are optimised for accessing the value of a specific field in
many documents.
It makes sense to use `_source` or stored fields when generating a
<<search-request-script-fields,script field>> for the top ten hits from a search
result but, for other search and aggregation use cases, always prefer using
doc values.
=========================================================
For instance:
[source,js]
-------------------------------
Update the default for include_type_name to false. (#37285) * Default include_type_name to false for get and put mappings. * Default include_type_name to false for get field mappings. * Add a constant for the default include_type_name value. * Default include_type_name to false for get and put index templates. * Default include_type_name to false for create index. * Update create index calls in REST documentation to use include_type_name=true. * Some minor clean-ups around the get index API. * In REST tests, use include_type_name=true by default for index creation. * Make sure to use 'expression == false'. * Clarify the different IndexTemplateMetaData toXContent methods. * Fix FullClusterRestartIT#testSnapshotRestore. * Fix the ml_anomalies_default_mappings test. * Fix GetFieldMappingsResponseTests and GetIndexTemplateResponseTests. We make sure to specify include_type_name=true during xContent parsing, so we continue to test the legacy typed responses. XContent generation for the typeless responses is currently only covered by REST tests, but we will be adding unit test coverage for these as we implement each typeless API in the Java HLRC. This commit also refactors GetMappingsResponse to follow the same appraoch as the other mappings-related responses, where we read include_type_name out of the xContent params, instead of creating a second toXContent method. This gives better consistency in the response parsing code. * Fix more REST tests. * Improve some wording in the create index documentation. * Add a note about types removal in the create index docs. * Fix SmokeTestMonitoringWithSecurityIT#testHTTPExporterWithSSL. * Make sure to mention include_type_name in the REST docs for affected APIs. * Make sure to use 'expression == false' in FullClusterRestartIT. * Mention include_type_name in the REST templates docs.
2019-01-14 16:08:01 -05:00
PUT my_index?include_type_name=true
{
"mappings": {
"_doc": {
"properties": {
"title": { <1>
"type": "text"
},
"first_name": {
"type": "text",
"store": true
},
"last_name": {
"type": "text",
"store": true
}
}
}
}
}
PUT my_index/_doc/1?refresh
{
"title": "Mr",
"first_name": "Barry",
"last_name": "White"
}
GET my_index/_search
{
"script_fields": {
"source": {
"script": {
"lang": "painless",
"source": "params._source.title + ' ' + params._source.first_name + ' ' + params._source.last_name" <2>
}
},
"stored_fields": {
"script": {
"lang": "painless",
"source": "params._fields['first_name'].value + ' ' + params._fields['last_name'].value"
}
}
}
}
-------------------------------
// CONSOLE
<1> The `title` field is not stored and so cannot be used with the `_fields[]` syntax.
<2> The `title` field can still be accessed from the `_source`.
[TIP]
.Stored vs `_source`
=======================================================
The `_source` field is just a special stored field, so the performance is
similar to that of other stored fields. The `_source` provides access to the
original document body that was indexed (including the ability to distinguish
`null` values from empty fields, single-value arrays from plain scalars, etc).
The only time it really makes sense to use stored fields instead of the
`_source` field is when the `_source` is very large and it is less costly to
access a few small stored fields instead of the entire `_source`.
=======================================================