lang-expressions should use DoubleValuesSource, not ValueSource (#53661)

DoubleValuesSource is the type-safe replacement for ValueSource in the lucene
core. Most of elasticsearch has moved to use these, but lang-expressions is still
using the old version. This commit migrates lang-expressions as well.
This commit is contained in:
Alan Woodward 2020-03-23 14:47:42 +00:00
parent 754d071c4e
commit 0c010e1bfc
16 changed files with 235 additions and 224 deletions

View File

@ -19,44 +19,36 @@
package org.elasticsearch.script.expression;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.DoubleValues;
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.SortedNumericDoubleValues;
import java.io.IOException;
/**
* A ValueSource to create FunctionValues to get the count of the number of values in a field for a document.
*/
final class CountMethodValueSource extends ValueSource {
IndexFieldData<?> fieldData;
final class CountMethodValueSource extends FieldDataBasedDoubleValuesSource {
CountMethodValueSource(IndexFieldData<?> fieldData) {
Objects.requireNonNull(fieldData);
this.fieldData = fieldData;
super(fieldData);
}
@Override
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
LeafNumericFieldData leafData = (LeafNumericFieldData) fieldData.load(leaf);
public DoubleValues getValues(LeafReaderContext ctx, DoubleValues scores) {
LeafNumericFieldData leafData = (LeafNumericFieldData) fieldData.load(ctx);
final SortedNumericDoubleValues values = leafData.getDoubleValues();
return new DoubleDocValues(this) {
return new DoubleValues() {
@Override
public double doubleVal(int doc) throws IOException {
if (values.advanceExact(doc)) {
return values.docValueCount();
} else {
return 0;
}
public double doubleValue() {
return values.docValueCount();
}
@Override
public boolean advanceExact(int doc) throws IOException {
return values.advanceExact(doc);
}
};
}
@ -65,19 +57,18 @@ final class CountMethodValueSource extends ValueSource {
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FieldDataValueSource that = (FieldDataValueSource) o;
CountMethodValueSource that = (CountMethodValueSource) o;
return fieldData.equals(that.fieldData);
}
@Override
public String toString() {
return "count: field(" + fieldData.getFieldName() + ")";
}
@Override
public int hashCode() {
return 31 * getClass().hashCode() + fieldData.hashCode();
}
@Override
public String description() {
return "count: field(" + fieldData.getFieldName() + ")";
}
}

View File

@ -19,12 +19,12 @@ package org.elasticsearch.script.expression;
* under the License.
*/
import java.util.Calendar;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.DoubleValuesSource;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.search.MultiValueMode;
import java.util.Calendar;
/**
* Expressions API for date fields.
*/
@ -56,7 +56,7 @@ final class DateField {
static final String GET_MINUTES_METHOD = "getMinutes";
static final String GET_SECONDS_METHOD = "getSeconds";
static ValueSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
static DoubleValuesSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
switch (variable) {
case VALUE_VARIABLE:
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
@ -69,7 +69,7 @@ final class DateField {
}
}
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
static DoubleValuesSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
switch (method) {
case GETVALUE_METHOD:
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);

View File

@ -19,21 +19,19 @@
package org.elasticsearch.script.expression;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;
import java.util.Map;
import java.util.Objects;
import java.util.TimeZone;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.DoubleValues;
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.NumericDoubleValues;
import org.elasticsearch.search.MultiValueMode;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;
import java.util.Objects;
import java.util.TimeZone;
/** Extracts a portion of a date field with {@code Calendar.get()} */
class DateMethodValueSource extends FieldDataValueSource {
@ -50,27 +48,26 @@ class DateMethodValueSource extends FieldDataValueSource {
}
@Override
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
public DoubleValues getValues(LeafReaderContext leaf, DoubleValues scores) {
LeafNumericFieldData leafData = (LeafNumericFieldData) fieldData.load(leaf);
final Calendar calendar = Calendar.getInstance(TimeZone.getTimeZone("UTC"), Locale.ROOT);
NumericDoubleValues docValues = multiValueMode.select(leafData.getDoubleValues());
return new DoubleDocValues(this) {
return new DoubleValues() {
@Override
public double doubleVal(int docId) throws IOException {
if (docValues.advanceExact(docId)) {
long millis = (long)docValues.doubleValue();
calendar.setTimeInMillis(millis);
return calendar.get(calendarType);
} else {
return 0;
}
public double doubleValue() throws IOException {
calendar.setTimeInMillis((long)docValues.doubleValue());
return calendar.get(calendarType);
}
@Override
public boolean advanceExact(int doc) throws IOException {
return docValues.advanceExact(doc);
}
};
}
@Override
public String description() {
public String toString() {
return methodName + ": field(" + fieldData.getFieldName() + ")";
}

View File

@ -19,7 +19,7 @@ package org.elasticsearch.script.expression;
* under the License.
*/
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.DoubleValuesSource;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.search.MultiValueMode;
import org.joda.time.ReadableDateTime;
@ -30,7 +30,7 @@ import org.joda.time.ReadableDateTime;
final class DateObject {
// no instance
private DateObject() {}
// supported variables
static final String CENTURY_OF_ERA_VARIABLE = "centuryOfEra";
static final String DAY_OF_MONTH_VARIABLE = "dayOfMonth";
@ -50,7 +50,7 @@ final class DateObject {
static final String YEAR_VARIABLE = "year";
static final String YEAR_OF_CENTURY_VARIABLE = "yearOfCentury";
static final String YEAR_OF_ERA_VARIABLE = "yearOfEra";
// supported methods
static final String GETCENTURY_OF_ERA_METHOD = "getCenturyOfEra";
static final String GETDAY_OF_MONTH_METHOD = "getDayOfMonth";
@ -70,8 +70,8 @@ final class DateObject {
static final String GETYEAR_METHOD = "getYear";
static final String GETYEAR_OF_CENTURY_METHOD = "getYearOfCentury";
static final String GETYEAR_OF_ERA_METHOD = "getYearOfEra";
static ValueSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
static DoubleValuesSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
switch (variable) {
case CENTURY_OF_ERA_VARIABLE:
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getCenturyOfEra);
@ -110,12 +110,12 @@ final class DateObject {
case YEAR_OF_ERA_VARIABLE:
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, variable, ReadableDateTime::getYearOfEra);
default:
throw new IllegalArgumentException("Member variable [" + variable +
throw new IllegalArgumentException("Member variable [" + variable +
"] does not exist for date object on field [" + fieldName + "].");
}
}
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
static DoubleValuesSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
switch (method) {
case GETCENTURY_OF_ERA_METHOD:
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getCenturyOfEra);
@ -154,7 +154,7 @@ final class DateObject {
case GETYEAR_OF_ERA_METHOD:
return new DateObjectValueSource(fieldData, MultiValueMode.MIN, method, ReadableDateTime::getYearOfEra);
default:
throw new IllegalArgumentException("Member method [" + method +
throw new IllegalArgumentException("Member method [" + method +
"] does not exist for date object on field [" + fieldName + "].");
}
}

View File

@ -19,14 +19,8 @@
package org.elasticsearch.script.expression;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import java.util.function.ToIntFunction;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.DoubleValues;
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.NumericDoubleValues;
@ -35,6 +29,10 @@ import org.joda.time.DateTimeZone;
import org.joda.time.MutableDateTime;
import org.joda.time.ReadableDateTime;
import java.io.IOException;
import java.util.Objects;
import java.util.function.ToIntFunction;
/** Extracts a portion of a date field with joda time */
class DateObjectValueSource extends FieldDataValueSource {
@ -52,27 +50,26 @@ class DateObjectValueSource extends FieldDataValueSource {
}
@Override
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
public DoubleValues getValues(LeafReaderContext leaf, DoubleValues scores) {
LeafNumericFieldData leafData = (LeafNumericFieldData) fieldData.load(leaf);
MutableDateTime joda = new MutableDateTime(0, DateTimeZone.UTC);
NumericDoubleValues docValues = multiValueMode.select(leafData.getDoubleValues());
return new DoubleDocValues(this) {
return DoubleValues.withDefault(new DoubleValues() {
@Override
public double doubleVal(int docId) throws IOException {
if (docValues.advanceExact(docId)) {
long millis = (long)docValues.doubleValue();
joda.setMillis(millis);
return function.applyAsInt(joda);
} else {
return 0;
}
public double doubleValue() throws IOException {
joda.setMillis((long)docValues.doubleValue());
return function.applyAsInt(joda);
}
};
@Override
public boolean advanceExact(int doc) throws IOException {
return docValues.advanceExact(doc);
}
}, 0);
}
@Override
public String description() {
public String toString() {
return methodName + ": field(" + fieldData.getFieldName() + ")";
}

View File

@ -20,44 +20,39 @@
package org.elasticsearch.script.expression;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.DoubleValues;
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.SortedNumericDoubleValues;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
/**
* ValueSource to return non-zero if a field is missing.
* <p>
* This is essentially sugar over !count()
*/
final class EmptyMemberValueSource extends ValueSource {
final IndexFieldData<?> fieldData;
final class EmptyMemberValueSource extends FieldDataBasedDoubleValuesSource {
EmptyMemberValueSource(IndexFieldData<?> fieldData) {
this.fieldData = Objects.requireNonNull(fieldData);
super(fieldData);
}
@Override
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
public DoubleValues getValues(LeafReaderContext leaf, DoubleValues scores) {
LeafNumericFieldData leafData = (LeafNumericFieldData) fieldData.load(leaf);
final SortedNumericDoubleValues values = leafData.getDoubleValues();
return new DoubleDocValues(this) {
return DoubleValues.withDefault(new DoubleValues() {
@Override
public double doubleVal(int doc) throws IOException {
if (values.advanceExact(doc)) {
return 0;
} else {
return 1;
}
public double doubleValue() {
return 0;
}
};
@Override
public boolean advanceExact(int doc) throws IOException {
return values.advanceExact(doc);
}
}, 1);
}
@Override
@ -71,12 +66,12 @@ final class EmptyMemberValueSource extends ValueSource {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
EmptyMemberValueSource other = (EmptyMemberValueSource) obj;
if (!fieldData.equals(other.fieldData)) return false;
return true;
return fieldData.equals(other.fieldData);
}
@Override
public String description() {
public String toString() {
return "empty: field(" + fieldData.getFieldName() + ")";
}
}

View File

@ -23,8 +23,8 @@ import org.apache.lucene.expressions.Expression;
import org.apache.lucene.expressions.SimpleBindings;
import org.apache.lucene.expressions.js.JavascriptCompiler;
import org.apache.lucene.expressions.js.VariableContext;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.valuesource.DoubleConstValueSource;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.SortField;
import org.elasticsearch.SpecialPermission;
import org.elasticsearch.common.Nullable;
@ -256,9 +256,9 @@ public class ExpressionScriptEngine implements ScriptEngine {
} else {
// delegate valuesource creation based on field's type
// there are three types of "fields" to expressions, and each one has a different "api" of variables and methods.
final ValueSource valueSource = getDocValueSource(variable, lookup);
needsScores |= valueSource.getSortField(false).needsScores();
bindings.add(variable, valueSource.asDoubleValuesSource());
final DoubleValuesSource valueSource = getDocValueSource(variable, lookup);
needsScores |= valueSource.needsScores();
bindings.add(variable, valueSource);
}
} catch (Exception e) {
// we defer "binding" of variables until here: give context for that variable
@ -280,8 +280,7 @@ public class ExpressionScriptEngine implements ScriptEngine {
} else {
// delegate valuesource creation based on field's type
// there are three types of "fields" to expressions, and each one has a different "api" of variables and methods.
final ValueSource valueSource = getDocValueSource(variable, lookup);
bindings.add(variable, valueSource.asDoubleValuesSource());
bindings.add(variable, getDocValueSource(variable, lookup));
}
} catch (Exception e) {
// we defer "binding" of variables until here: give context for that variable
@ -315,9 +314,9 @@ public class ExpressionScriptEngine implements ScriptEngine {
} else {
// delegate valuesource creation based on field's type
// there are three types of "fields" to expressions, and each one has a different "api" of variables and methods.
final ValueSource valueSource = getDocValueSource(variable, lookup);
needsScores |= valueSource.getSortField(false).needsScores();
bindings.add(variable, valueSource.asDoubleValuesSource());
final DoubleValuesSource valueSource = getDocValueSource(variable, lookup);
needsScores |= valueSource.needsScores();
bindings.add(variable, valueSource);
}
} catch (Exception e) {
// we defer "binding" of variables until here: give context for that variable
@ -334,8 +333,7 @@ public class ExpressionScriptEngine implements ScriptEngine {
if (vars != null && vars.containsKey(variable)) {
bindFromParams(vars, bindings, variable);
} else {
final ValueSource valueSource = getDocValueSource(variable, lookup);
bindings.add(variable, valueSource.asDoubleValuesSource());
bindings.add(variable, getDocValueSource(variable, lookup));
}
} catch (Exception e) {
throw convertToScriptException("link error", expr.sourceText, variable, e);
@ -387,9 +385,9 @@ public class ExpressionScriptEngine implements ScriptEngine {
} else {
// delegate valuesource creation based on field's type
// there are three types of "fields" to expressions, and each one has a different "api" of variables and methods.
final ValueSource valueSource = getDocValueSource(variable, lookup);
needsScores |= valueSource.getSortField(false).needsScores();
bindings.add(variable, valueSource.asDoubleValuesSource());
final DoubleValuesSource valueSource = getDocValueSource(variable, lookup);
needsScores |= valueSource.needsScores();
bindings.add(variable, valueSource);
}
} catch (Exception e) {
// we defer "binding" of variables until here: give context for that variable
@ -417,7 +415,7 @@ public class ExpressionScriptEngine implements ScriptEngine {
throw new ScriptException(message, cause, stack, source, NAME);
}
private static ValueSource getDocValueSource(String variable, SearchLookup lookup) throws ParseException {
private static DoubleValuesSource getDocValueSource(String variable, SearchLookup lookup) throws ParseException {
VariableContext[] parts = VariableContext.parse(variable);
if (parts[0].text.equals("doc") == false) {
throw new ParseException("Unknown variable [" + parts[0].text + "]", 0);
@ -468,7 +466,7 @@ public class ExpressionScriptEngine implements ScriptEngine {
}
IndexFieldData<?> fieldData = lookup.doc().getForField(fieldType);
final ValueSource valueSource;
final DoubleValuesSource valueSource;
if (fieldType instanceof GeoPointFieldType) {
// geo
if (methodname == null) {

View File

@ -0,0 +1,53 @@
/*
* Licensed to Elasticsearch under one or more contributor
* license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright
* ownership. Elasticsearch licenses this file to you under
* the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.elasticsearch.script.expression;
import org.apache.lucene.index.DocValues;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.DoubleValuesSource;
import org.apache.lucene.search.IndexSearcher;
import org.elasticsearch.index.fielddata.IndexFieldData;
import java.util.Objects;
abstract class FieldDataBasedDoubleValuesSource extends DoubleValuesSource {
FieldDataBasedDoubleValuesSource(IndexFieldData<?> fieldData) {
this.fieldData = Objects.requireNonNull(fieldData);
}
protected final IndexFieldData<?> fieldData;
@Override
public boolean needsScores() {
return false;
}
@Override
public DoubleValuesSource rewrite(IndexSearcher reader) {
return this;
}
@Override
public boolean isCacheable(LeafReaderContext ctx) {
return DocValues.isCacheable(ctx, fieldData.getFieldName());
}
}

View File

@ -19,29 +19,26 @@
package org.elasticsearch.script.expression;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.DoubleValues;
import org.elasticsearch.index.fielddata.LeafNumericFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.NumericDoubleValues;
import org.elasticsearch.search.MultiValueMode;
import java.io.IOException;
import java.util.Objects;
/**
* A {@link ValueSource} wrapper for field data.
*/
class FieldDataValueSource extends ValueSource {
class FieldDataValueSource extends FieldDataBasedDoubleValuesSource {
final IndexFieldData<?> fieldData;
final MultiValueMode multiValueMode;
protected FieldDataValueSource(IndexFieldData<?> fieldData, MultiValueMode multiValueMode) {
this.fieldData = Objects.requireNonNull(fieldData);
super(fieldData);
this.multiValueMode = Objects.requireNonNull(multiValueMode);
}
@ -65,24 +62,25 @@ class FieldDataValueSource extends ValueSource {
}
@Override
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
public DoubleValues getValues(LeafReaderContext leaf, DoubleValues scores) {
LeafNumericFieldData leafData = (LeafNumericFieldData) fieldData.load(leaf);
NumericDoubleValues docValues = multiValueMode.select(leafData.getDoubleValues());
return new DoubleDocValues(this) {
@Override
public double doubleVal(int doc) throws IOException {
if (docValues.advanceExact(doc)) {
return new DoubleValues() {
@Override
public double doubleValue() throws IOException {
return docValues.doubleValue();
} else {
return 0;
}
}
@Override
public boolean advanceExact(int doc) throws IOException {
return docValues.advanceExact(doc);
}
};
}
@Override
public String description() {
public String toString() {
return "field(" + fieldData.getFieldName() + ")";
}
}

View File

@ -19,43 +19,38 @@
package org.elasticsearch.script.expression;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.elasticsearch.index.fielddata.LeafGeoPointFieldData;
import org.apache.lucene.search.DoubleValues;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.LeafGeoPointFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import java.io.IOException;
/**
* ValueSource to return non-zero if a field is missing.
*/
final class GeoEmptyValueSource extends ValueSource {
IndexFieldData<?> fieldData;
final class GeoEmptyValueSource extends FieldDataBasedDoubleValuesSource {
GeoEmptyValueSource(IndexFieldData<?> fieldData) {
this.fieldData = Objects.requireNonNull(fieldData);
super(fieldData);
}
@Override
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
public DoubleValues getValues(LeafReaderContext leaf, DoubleValues scores) {
LeafGeoPointFieldData leafData = (LeafGeoPointFieldData) fieldData.load(leaf);
final MultiGeoPointValues values = leafData.getGeoPointValues();
return new DoubleDocValues(this) {
return DoubleValues.withDefault(new DoubleValues() {
@Override
public double doubleVal(int doc) throws IOException {
if (values.advanceExact(doc)) {
return 1;
} else {
return 0;
}
public double doubleValue() {
return 1;
}
};
@Override
public boolean advanceExact(int doc) throws IOException {
return values.advanceExact(doc);
}
}, 0);
}
@Override
@ -69,12 +64,12 @@ final class GeoEmptyValueSource extends ValueSource {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
GeoEmptyValueSource other = (GeoEmptyValueSource) obj;
if (!fieldData.equals(other.fieldData)) return false;
return true;
return fieldData.equals(other.fieldData);
}
@Override
public String description() {
public String toString() {
return "empty: field(" + fieldData.getFieldName() + ")";
}
}

View File

@ -19,7 +19,7 @@ package org.elasticsearch.script.expression;
* under the License.
*/
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.DoubleValuesSource;
import org.elasticsearch.index.fielddata.IndexFieldData;
/**
@ -28,18 +28,18 @@ import org.elasticsearch.index.fielddata.IndexFieldData;
final class GeoField {
// no instance
private GeoField() {}
// supported variables
static final String EMPTY_VARIABLE = "empty";
static final String LAT_VARIABLE = "lat";
static final String LON_VARIABLE = "lon";
// supported methods
static final String ISEMPTY_METHOD = "isEmpty";
static final String GETLAT_METHOD = "getLat";
static final String GETLON_METHOD = "getLon";
static ValueSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
static DoubleValuesSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
switch (variable) {
case EMPTY_VARIABLE:
return new GeoEmptyValueSource(fieldData);
@ -51,8 +51,8 @@ final class GeoField {
throw new IllegalArgumentException("Member variable [" + variable + "] does not exist for geo field [" + fieldName + "].");
}
}
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
static DoubleValuesSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
switch (method) {
case ISEMPTY_METHOD:
return new GeoEmptyValueSource(fieldData);

View File

@ -19,43 +19,38 @@
package org.elasticsearch.script.expression;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.DoubleValues;
import org.elasticsearch.index.fielddata.LeafGeoPointFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import java.io.IOException;
/**
* ValueSource to return latitudes as a double "stream" for geopoint fields
*/
final class GeoLatitudeValueSource extends ValueSource {
final IndexFieldData<?> fieldData;
final class GeoLatitudeValueSource extends FieldDataBasedDoubleValuesSource {
GeoLatitudeValueSource(IndexFieldData<?> fieldData) {
this.fieldData = Objects.requireNonNull(fieldData);
super(fieldData);
}
@Override
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
public DoubleValues getValues(LeafReaderContext leaf, DoubleValues scores) {
LeafGeoPointFieldData leafData = (LeafGeoPointFieldData) fieldData.load(leaf);
final MultiGeoPointValues values = leafData.getGeoPointValues();
return new DoubleDocValues(this) {
return DoubleValues.withDefault(new DoubleValues() {
@Override
public double doubleVal(int doc) throws IOException {
if (values.advanceExact(doc)) {
return values.nextValue().getLat();
} else {
return 0.0;
}
public double doubleValue() throws IOException {
return values.nextValue().getLat();
}
};
@Override
public boolean advanceExact(int doc) throws IOException {
return values.advanceExact(doc);
}
}, 0);
}
@Override
@ -69,12 +64,11 @@ final class GeoLatitudeValueSource extends ValueSource {
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
GeoLatitudeValueSource other = (GeoLatitudeValueSource) obj;
if (!fieldData.equals(other.fieldData)) return false;
return true;
return fieldData.equals(other.fieldData);
}
@Override
public String description() {
public String toString() {
return "lat: field(" + fieldData.getFieldName() + ")";
}
}

View File

@ -19,43 +19,38 @@
package org.elasticsearch.script.expression;
import java.io.IOException;
import java.util.Map;
import java.util.Objects;
import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.queries.function.FunctionValues;
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.queries.function.docvalues.DoubleDocValues;
import org.apache.lucene.search.DoubleValues;
import org.elasticsearch.index.fielddata.LeafGeoPointFieldData;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.index.fielddata.MultiGeoPointValues;
import java.io.IOException;
/**
* ValueSource to return longitudes as a double "stream" for geopoint fields
*/
final class GeoLongitudeValueSource extends ValueSource {
final IndexFieldData<?> fieldData;
final class GeoLongitudeValueSource extends FieldDataBasedDoubleValuesSource {
GeoLongitudeValueSource(IndexFieldData<?> fieldData) {
this.fieldData = Objects.requireNonNull(fieldData);
super(fieldData);
}
@Override
@SuppressWarnings("rawtypes") // ValueSource uses a rawtype
public FunctionValues getValues(Map context, LeafReaderContext leaf) throws IOException {
public DoubleValues getValues(LeafReaderContext leaf, DoubleValues scores) {
LeafGeoPointFieldData leafData = (LeafGeoPointFieldData) fieldData.load(leaf);
final MultiGeoPointValues values = leafData.getGeoPointValues();
return new DoubleDocValues(this) {
return DoubleValues.withDefault(new DoubleValues() {
@Override
public double doubleVal(int doc) throws IOException {
if (values.advanceExact(doc)) {
return values.nextValue().getLon();
} else {
return 0.0;
}
public double doubleValue() throws IOException {
return values.nextValue().getLon();
}
};
@Override
public boolean advanceExact(int doc) throws IOException {
return values.advanceExact(doc);
}
}, 0.0);
}
@Override
@ -74,7 +69,7 @@ final class GeoLongitudeValueSource extends ValueSource {
}
@Override
public String description() {
public String toString() {
return "lon: field(" + fieldData.getFieldName() + ")";
}
}

View File

@ -19,7 +19,7 @@ package org.elasticsearch.script.expression;
* under the License.
*/
import org.apache.lucene.queries.function.ValueSource;
import org.apache.lucene.search.DoubleValuesSource;
import org.elasticsearch.index.fielddata.IndexFieldData;
import org.elasticsearch.search.MultiValueMode;
@ -46,7 +46,7 @@ final class NumericField {
static final String SUM_METHOD = "sum";
static final String COUNT_METHOD = "count";
static ValueSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
static DoubleValuesSource getVariable(IndexFieldData<?> fieldData, String fieldName, String variable) {
switch (variable) {
case VALUE_VARIABLE:
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);
@ -60,7 +60,7 @@ final class NumericField {
}
}
static ValueSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
static DoubleValuesSource getMethod(IndexFieldData<?> fieldData, String fieldName, String method) {
switch (method) {
case GETVALUE_METHOD:
return new FieldDataValueSource(fieldData, MultiValueMode.MIN);

View File

@ -80,7 +80,7 @@ final class ReplaceableConstDoubleValueSource extends DoubleValuesSource {
}
@Override
public DoubleValuesSource rewrite(IndexSearcher reader) throws IOException {
public DoubleValuesSource rewrite(IndexSearcher reader) {
return this;
}
}

View File

@ -21,8 +21,6 @@ package org.elasticsearch.script.expression;
import org.apache.lucene.search.DoubleValues;
import java.io.IOException;
/**
* A support class for an executable expression script that allows the double returned
* by a {@link DoubleValues} to be modified.
@ -35,12 +33,12 @@ final class ReplaceableConstDoubleValues extends DoubleValues {
}
@Override
public double doubleValue() throws IOException {
public double doubleValue() {
return value;
}
@Override
public boolean advanceExact(int doc) throws IOException {
public boolean advanceExact(int doc) {
return true;
}
}