Skip to content

Commit

Permalink
Handle missing and multiple values in script
Browse files Browse the repository at this point in the history
Previously in script for numeric fields, there was no way to check if
a document is missing a value. Also certain operations on multiple-
values fields were missing.

This PR adds the following:

- add the following functions for multiple-valued numeric fields:
    doc['field'].min returns the minumum amoung values
    doc['field'].max returns the maximum amoung values
    doc['field'].sum returns the sum of amoung values
    doc['field'].avg returns the average of values

- return null for doc['field'] if a document is missing a 'field1':
    Now we can do this:
    if (doc['field'] == null) {return -1;} return doc['field'].value; or
    doc['field']?.value ?: -1
    This new behaviour will only work if the following system property is set:
    `export ES_JAVA_OPTS="-Des.script.null_for_missing_value=true"'

Closes elastic#29286
  • Loading branch information
mayya-sharipova committed May 1, 2018
1 parent 5aeab57 commit 3b42f1f
Show file tree
Hide file tree
Showing 6 changed files with 26 additions and 5 deletions.
1 change: 1 addition & 0 deletions docs/CHANGELOG.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
=== Breaking Java Changes

=== Deprecations
Returning 0 for missing numeric fields in script is deprecated. PR: 29611

=== New Features

Expand Down
18 changes: 14 additions & 4 deletions docs/painless/painless-getting-started.asciidoc
Original file line number Diff line number Diff line change
Expand Up @@ -121,12 +121,22 @@ GET hockey/_search
// CONSOLE

[float]
===== Missing and multiple values
===== Missing values

If a document is missing a field `field`, `doc['field']` for this document
will return null.
Currently by default, if a document is missing a numeric field `field`,
`doc['field'].value` returns `0` for this document. This default behaviour
will be changed in the next major version of elasticsearch:
if a document is missing a field `field`, `doc['field']` for this document
will return `null`. You can set a system property
`export ES_JAVA_OPTS="-Des.script.null_for_missing_value=true"' on a node
to make this node's behaviour compatible with the future major version.
Otherwise, every time the node starts a deprecation warning will remind you
about this forthcoming change.

There is also a number of operations designed for numeric fields,

===== Multiple values

There is a number of operations designed for numeric fields,
if a document has multiple values in such a field:

- `doc['field'].min` - gets the minimum value among values
Expand Down
1 change: 1 addition & 0 deletions modules/lang-painless/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ esplugin {
}

integTestCluster {
systemProperty 'es.script.null_for_missing_value', 'true'
module project.project(':modules:mapper-extras')
}

Expand Down
4 changes: 4 additions & 0 deletions server/src/main/java/org/elasticsearch/node/Node.java
Original file line number Diff line number Diff line change
Expand Up @@ -716,6 +716,10 @@ public void onTimeout(TimeValue timeout) {
writePortsFile("transport", transport.boundAddress());
}

if (!ScriptModule.NULL_FOR_MISSING_VALUE)
logger.warn("Script: returning 0 for missing numeric values is deprecated. " +
"Set system property '-Des.script.null_for_missing_value=true' to make behaviour compatible with future major versions.");

logger.info("started");

pluginsService.filterPlugins(ClusterPlugin.class).forEach(ClusterPlugin::onNodeStarted);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.elasticsearch.common.Booleans;
import org.elasticsearch.common.settings.ClusterSettings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.plugins.ScriptPlugin;
Expand All @@ -52,6 +53,9 @@ public class ScriptModule {
).collect(Collectors.toMap(c -> c.name, Function.identity()));
}

public static final boolean NULL_FOR_MISSING_VALUE =
Booleans.parseBoolean(System.getProperty("es.script.null_for_missing_value", "false"));

private final ScriptService scriptService;

public ScriptModule(Settings settings, List<ScriptPlugin> scriptPlugins) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.mapper.MappedFieldType;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.script.ScriptModule;

import java.io.IOException;
import java.security.AccessController;
Expand Down Expand Up @@ -92,7 +93,7 @@ public ScriptDocValues<?> run() {
}
try {
boolean docHasValues = scriptValues.setNextDocId(docId);
if (!docHasValues) return null;
if (!docHasValues && ScriptModule.NULL_FOR_MISSING_VALUE) return null;
} catch (IOException e) {
throw ExceptionsHelper.convertToElastic(e);
}
Expand Down

0 comments on commit 3b42f1f

Please sign in to comment.