Skip to content

Commit

Permalink
Share data between DocValuesField and ScriptDocValues (elastic#79587)
Browse files Browse the repository at this point in the history
This change makes it so there is only one path to retrieve values for scripting through the newly 
introduced fields API. To support backwards compatibility of ScriptDocValues, DocValuesField will 
return ScriptDocValues for continued doc access where the values are shared, so there is no 
double loading of field data. For now, for unsupported DocValuesFields we have a 
DelegateDocValuesField that returns the ScriptDocValues for long, double, String, etc.
  • Loading branch information
jdconrad authored and Adam Locke committed Oct 28, 2021
1 parent d547eae commit 3495237
Show file tree
Hide file tree
Showing 30 changed files with 241 additions and 154 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,10 @@ class org.elasticsearch.script.field.Field @dynamic_type {
}

class org.elasticsearch.script.DocBasedScript {
org.elasticsearch.script.field.Field field(String)
org.elasticsearch.script.field.Field field(String)
}

class org.elasticsearch.script.field.DelegateDocValuesField @dynamic_type {
def getValue(def)
List getValues()
}
Original file line number Diff line number Diff line change
Expand Up @@ -154,3 +154,32 @@ setup:
- match: { error.failed_shards.0.reason.caused_by.reason: "no paths escape from while loop" }
- match: { error.failed_shards.0.reason.type: "script_exception" }
- match: { error.failed_shards.0.reason.reason: "compile error" }

---
"Scripted Field with error accessing an unsupported field via the script fields api":
- do:
catch: bad_request
search:
rest_total_hits_as_int: true
body:
script_fields:
bar:
script:
source: "field('foo').getValue('')"

- match: { error.failed_shards.0.reason.caused_by.type: "unsupported_operation_exception" }
- match: { error.failed_shards.0.reason.caused_by.reason: "field [foo] is not supported through the fields api, use [doc] instead"}

- do:
catch: bad_request
search:
rest_total_hits_as_int: true
body:
script_fields:
bar:
script:
source: "field('foo').getValues()"

- match: { error.failed_shards.0.reason.caused_by.type: "unsupported_operation_exception" }
- match: { error.failed_shards.0.reason.caused_by.reason: "field [foo] is not supported through the fields api, use [doc] instead" }

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
import org.elasticsearch.common.Explicit;
import org.elasticsearch.common.settings.Setting;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;
import org.elasticsearch.xcontent.XContentParser;
import org.elasticsearch.xcontent.XContentParser.Token;
import org.elasticsearch.common.xcontent.support.XContentMapValues;
Expand Down Expand Up @@ -505,8 +507,8 @@ private static class ScaledFloatLeafFieldData implements LeafNumericFieldData {
}

@Override
public ScriptDocValues.Doubles getScriptValues() {
return new ScriptDocValues.Doubles(getDoubleValues());
public DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new ScriptDocValues.Doubles(getDoubleValues()), name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@
import org.elasticsearch.index.mapper.IpFieldMapper;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.script.IpFieldScript;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
import org.elasticsearch.search.aggregations.support.ValuesSourceType;

Expand Down Expand Up @@ -50,8 +52,8 @@ public BinaryScriptLeafFieldData loadDirect(LeafReaderContext context) throws Ex
IpFieldScript script = leafFactory.newInstance(context);
return new BinaryScriptLeafFieldData() {
@Override
public ScriptDocValues<String> getScriptValues() {
return new IpScriptDocValues(getBytesValues());
public DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new IpScriptDocValues(getBytesValues()), name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,17 +20,10 @@
*/
public interface LeafFieldData extends Accountable, Releasable {

/**
* Returns field values for use in scripting.
*/
ScriptDocValues<?> getScriptValues();

/**
* Returns an {@code Field} for use in accessing field values in scripting.
*/
default DocValuesField getScriptField(String name) {
throw new UnsupportedOperationException();
}
DocValuesField getScriptField(String name);

/**
* Return a String representation of the values.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@
import org.apache.lucene.index.LeafReaderContext;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.script.StringFieldScript;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
import org.elasticsearch.search.aggregations.support.ValuesSourceType;

Expand Down Expand Up @@ -42,8 +44,8 @@ public BinaryScriptLeafFieldData loadDirect(LeafReaderContext context) throws Ex
StringFieldScript script = leafFactory.newInstance(context);
return new BinaryScriptLeafFieldData() {
@Override
public ScriptDocValues<?> getScriptValues() {
return new ScriptDocValues.Strings(getBytesValues());
public DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new ScriptDocValues.Strings(getBytesValues()), name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.SortedBinaryDocValues;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;

import java.util.Collection;
import java.util.Collections;
Expand All @@ -25,8 +27,8 @@ public final SortedBinaryDocValues getBytesValues() {
}

@Override
public final ScriptDocValues.GeoPoints getScriptValues() {
return new ScriptDocValues.GeoPoints(getGeoPointValues());
public final DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new ScriptDocValues.GeoPoints(getGeoPointValues()), name);
}

public static LeafGeoPointFieldData empty(final int maxDoc) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@
import org.elasticsearch.index.fielddata.FieldData;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.SortedBinaryDocValues;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;

import java.util.Collection;
import java.util.Collections;
Expand All @@ -34,8 +36,8 @@ protected AbstractLeafOrdinalsFieldData(Function<SortedSetDocValues, ScriptDocVa
}

@Override
public final ScriptDocValues<?> getScriptValues() {
return scriptFunction.apply(getOrdinalsValues());
public final DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(scriptFunction.apply(getOrdinalsValues()), name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,12 @@
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReader;
import org.apache.lucene.util.Accountable;
import org.elasticsearch.index.fielddata.LeafFieldData;
import org.elasticsearch.index.fielddata.FieldData;
import org.elasticsearch.index.fielddata.LeafFieldData;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.ScriptDocValues.Strings;
import org.elasticsearch.index.fielddata.SortedBinaryDocValues;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;

import java.io.IOException;
import java.util.Collection;
Expand Down Expand Up @@ -44,8 +45,8 @@ public SortedBinaryDocValues getBytesValues() {
}

@Override
public Strings getScriptValues() {
return new ScriptDocValues.Strings(getBytesValues());
public DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new ScriptDocValues.Strings(getBytesValues()), name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,9 @@
package org.elasticsearch.index.fielddata.plain;

import org.apache.lucene.index.BinaryDocValues;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;


final class BytesBinaryDVLeafFieldData extends AbstractBinaryDVLeafFieldData {
Expand All @@ -19,8 +20,8 @@ final class BytesBinaryDVLeafFieldData extends AbstractBinaryDVLeafFieldData {
}

@Override
public ScriptDocValues<BytesRef> getScriptValues() {
return new ScriptDocValues.BytesRefs(getBytesValues());
public DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new ScriptDocValues.BytesRefs(getBytesValues()), name);
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.SortedBinaryDocValues;
import org.elasticsearch.index.fielddata.SortedNumericDoubleValues;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;
import org.elasticsearch.search.DocValueFormat;

import java.io.IOException;
Expand All @@ -40,8 +42,8 @@ public long ramBytesUsed() {
}

@Override
public final ScriptDocValues<Double> getScriptValues() {
return new ScriptDocValues.Doubles(getDoubleValues());
public final DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new ScriptDocValues.Doubles(getDoubleValues()), name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.SortedBinaryDocValues;
import org.elasticsearch.index.fielddata.SortedNumericDoubleValues;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;
import org.elasticsearch.search.DocValueFormat;

import java.io.IOException;
Expand All @@ -27,7 +29,7 @@ public abstract class LeafLongFieldData implements LeafNumericFieldData {

private final long ramBytesUsed;
/**
* Type of this field. Used to expose appropriate types in {@link #getScriptValues()}.
* Type of this field. Used to expose appropriate types in {@link #getScriptField(String)}}.
*/
private final NumericType numericType;

Expand All @@ -42,18 +44,19 @@ public long ramBytesUsed() {
}

@Override
public final ScriptDocValues<?> getScriptValues() {
public final DocValuesField getScriptField(String name) {
switch (numericType) {
// for now, dates and nanoseconds are treated the same, which also means, that the precision is only on millisecond level
case DATE:
return new ScriptDocValues.Dates(getLongValues(), false);
return new DelegateDocValuesField(new ScriptDocValues.Dates(getLongValues(), false), name);
case DATE_NANOSECONDS:
assert this instanceof SortedNumericIndexFieldData.NanoSecondFieldData;
return new ScriptDocValues.Dates(((SortedNumericIndexFieldData.NanoSecondFieldData) this).getLongValuesAsNanos(), true);
return new DelegateDocValuesField(
new ScriptDocValues.Dates(((SortedNumericIndexFieldData.NanoSecondFieldData) this).getLongValuesAsNanos(), true), name);
case BOOLEAN:
return new ScriptDocValues.Booleans(getLongValues());
return new DelegateDocValuesField(new ScriptDocValues.Booleans(getLongValues()), name);
default:
return new ScriptDocValues.Longs(getLongValues());
return new DelegateDocValuesField(new ScriptDocValues.Longs(getLongValues()), name);
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,14 +10,16 @@

import org.apache.lucene.index.BinaryDocValues;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;

final class StringBinaryDVLeafFieldData extends AbstractBinaryDVLeafFieldData {
StringBinaryDVLeafFieldData(BinaryDocValues values) {
super(values);
}

@Override
public ScriptDocValues<String> getScriptValues() {
return new ScriptDocValues.Strings(getBytesValues());
public DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new ScriptDocValues.Strings(getBytesValues()), name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.indices.IndicesService;
import org.elasticsearch.indices.breaker.CircuitBreakerService;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;
import org.elasticsearch.search.DocValueFormat;
import org.elasticsearch.search.MultiValueMode;
import org.elasticsearch.search.aggregations.support.CoreValuesSourceType;
Expand Down Expand Up @@ -211,8 +213,8 @@ public long ramBytesUsed() {
}

@Override
public ScriptDocValues<?> getScriptValues() {
return new ScriptDocValues.Strings(getBytesValues());
public DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(new ScriptDocValues.Strings(getBytesValues()), name);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
import org.apache.lucene.util.Accountable;
import org.apache.lucene.util.BytesRef;
import org.elasticsearch.index.fielddata.AbstractSortedSetDocValues;
import org.elasticsearch.index.fielddata.LeafOrdinalsFieldData;
import org.elasticsearch.index.fielddata.FieldData;
import org.elasticsearch.index.fielddata.ScriptDocValues;
import org.elasticsearch.index.fielddata.LeafOrdinalsFieldData;
import org.elasticsearch.index.fielddata.SortedBinaryDocValues;
import org.elasticsearch.index.fielddata.plain.AbstractLeafOrdinalsFieldData;
import org.elasticsearch.script.field.DelegateDocValuesField;
import org.elasticsearch.script.field.DocValuesField;

import java.io.IOException;
import java.io.UncheckedIOException;
Expand Down Expand Up @@ -79,9 +80,9 @@ public void close() {
}

@Override
public ScriptDocValues<?> getScriptValues() {
return AbstractLeafOrdinalsFieldData.DEFAULT_SCRIPT_FUNCTION
.apply(getOrdinalsValues());
public DocValuesField getScriptField(String name) {
return new DelegateDocValuesField(
AbstractLeafOrdinalsFieldData.DEFAULT_SCRIPT_FUNCTION.apply(getOrdinalsValues()), name);
}

@Override
Expand Down
Loading

0 comments on commit 3495237

Please sign in to comment.