diff --git a/core/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java b/core/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java index dcd1399bf51..fe7d097638f 100644 --- a/core/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java +++ b/core/src/main/java/org/elasticsearch/index/query/functionscore/DecayFunctionBuilder.java @@ -43,8 +43,9 @@ import org.elasticsearch.index.fielddata.IndexNumericFieldData; import org.elasticsearch.index.fielddata.MultiGeoPointValues; import org.elasticsearch.index.fielddata.NumericDoubleValues; import org.elasticsearch.index.fielddata.SortedNumericDoubleValues; -import org.elasticsearch.index.mapper.GeoPointFieldMapper.GeoPointFieldType; +import org.elasticsearch.index.fielddata.SortingNumericDoubleValues; import org.elasticsearch.index.mapper.DateFieldMapper; +import org.elasticsearch.index.mapper.GeoPointFieldMapper.GeoPointFieldType; import org.elasticsearch.index.mapper.MappedFieldType; import org.elasticsearch.index.mapper.NumberFieldMapper; import org.elasticsearch.index.query.QueryShardContext; @@ -346,22 +347,23 @@ public abstract class DecayFunctionBuilder @Override protected NumericDoubleValues distance(LeafReaderContext context) { final MultiGeoPointValues geoPointValues = fieldData.load(context).getGeoPointValues(); - return mode.select(new MultiValueMode.UnsortedNumericDoubleValues() { - @Override - public int docValueCount() { - return geoPointValues.docValueCount(); - } - + return mode.select(new SortingNumericDoubleValues() { @Override public boolean advanceExact(int docId) throws IOException { - return geoPointValues.advanceExact(docId); - } - - @Override - public double nextValue() throws IOException { - GeoPoint other = geoPointValues.nextValue(); - return Math.max(0.0d, - distFunction.calculate(origin.lat(), origin.lon(), other.lat(), other.lon(), DistanceUnit.METERS) - offset); + if (geoPointValues.advanceExact(docId)) { + int n = geoPointValues.docValueCount(); + resize(n); + for (int i = 0; i < n; i++) { + GeoPoint other = geoPointValues.nextValue(); + double distance = distFunction.calculate( + origin.lat(), origin.lon(), other.lat(), other.lon(), DistanceUnit.METERS); + values[i] = Math.max(0.0d, distance - offset); + } + sort(); + return true; + } else { + return false; + } } }, 0.0); } @@ -427,20 +429,20 @@ public abstract class DecayFunctionBuilder @Override protected NumericDoubleValues distance(LeafReaderContext context) { final SortedNumericDoubleValues doubleValues = fieldData.load(context).getDoubleValues(); - return mode.select(new MultiValueMode.UnsortedNumericDoubleValues() { + return mode.select(new SortingNumericDoubleValues() { @Override - public int docValueCount() { - return doubleValues.docValueCount(); - } - - @Override - public boolean advanceExact(int doc) throws IOException { - return doubleValues.advanceExact(doc); - } - - @Override - public double nextValue() throws IOException { - return Math.max(0.0d, Math.abs(doubleValues.nextValue() - origin) - offset); + public boolean advanceExact(int docId) throws IOException { + if (doubleValues.advanceExact(docId)) { + int n = doubleValues.docValueCount(); + resize(n); + for (int i = 0; i < n; i++) { + values[i] = Math.max(0.0d, Math.abs(doubleValues.nextValue() - origin) - offset); + } + sort(); + return true; + } else { + return false; + } } }, 0.0); } @@ -542,10 +544,11 @@ public abstract class DecayFunctionBuilder if (distance.advanceExact(docId) == false) { return Explanation.noMatch("No value for the distance"); } + double value = distance.doubleValue(); return Explanation.match( (float) score(docId, subQueryScore.getValue()), "Function for field " + getFieldName() + ":", - func.explainFunction(getDistanceString(ctx, docId), distance.doubleValue(), scale)); + func.explainFunction(getDistanceString(ctx, docId), value, scale)); } }; } diff --git a/core/src/main/java/org/elasticsearch/search/MultiValueMode.java b/core/src/main/java/org/elasticsearch/search/MultiValueMode.java index 1195644e328..2d85c379f54 100644 --- a/core/src/main/java/org/elasticsearch/search/MultiValueMode.java +++ b/core/src/main/java/org/elasticsearch/search/MultiValueMode.java @@ -104,16 +104,6 @@ public enum MultiValueMode implements Writeable { } return totalCount > 0 ? totalValue : missingValue; } - - @Override - protected double pick(UnsortedNumericDoubleValues values) throws IOException { - final int count = values.docValueCount(); - double total = 0; - for (int index = 0; index < count; ++index) { - total += values.nextValue(); - } - return total; - } }, /** @@ -177,16 +167,6 @@ public enum MultiValueMode implements Writeable { } return totalValue/totalCount; } - - @Override - protected double pick(UnsortedNumericDoubleValues values) throws IOException { - final int count = values.docValueCount(); - double total = 0; - for (int index = 0; index < count; ++index) { - total += values.nextValue(); - } - return total/count; - } }, /** @@ -303,16 +283,6 @@ public enum MultiValueMode implements Writeable { } return hasValue ? ord : -1; } - - @Override - protected double pick(UnsortedNumericDoubleValues values) throws IOException { - int count = values.docValueCount(); - double min = Double.POSITIVE_INFINITY; - for (int index = 0; index < count; ++index) { - min = Math.min(values.nextValue(), min); - } - return min; - } }, /** @@ -419,16 +389,6 @@ public enum MultiValueMode implements Writeable { } return ord; } - - @Override - protected double pick(UnsortedNumericDoubleValues values) throws IOException { - int count = values.docValueCount(); - double max = Double.NEGATIVE_INFINITY; - for (int index = 0; index < count; ++index) { - max = Math.max(values.nextValue(), max); - } - return max; - } }; /** @@ -905,43 +865,6 @@ public enum MultiValueMode implements Writeable { throw new IllegalArgumentException("Unsupported sort mode: " + this); } - /** - * Return a {@link NumericDoubleValues} instance that can be used to sort documents - * with this mode and the provided values. When a document has no value, - * missingValue is returned. - * - * Allowed Modes: SUM, AVG, MIN, MAX - */ - public NumericDoubleValues select(final UnsortedNumericDoubleValues values, final double missingValue) { - return new NumericDoubleValues() { - private boolean hasValue; - - @Override - public boolean advanceExact(int doc) throws IOException { - hasValue = values.advanceExact(doc); - return true; - } - @Override - public double doubleValue() throws IOException { - return hasValue ? pick(values) : missingValue; - } - }; - } - - protected double pick(UnsortedNumericDoubleValues values) throws IOException { - throw new IllegalArgumentException("Unsupported sort mode: " + this); - } - - /** - * Interface allowing custom value generators to be used in MultiValueMode. - */ - // TODO: why do we need it??? - public interface UnsortedNumericDoubleValues { - boolean advanceExact(int doc) throws IOException; - int docValueCount() throws IOException; - double nextValue() throws IOException; - } - @Override public void writeTo(StreamOutput out) throws IOException { out.writeEnum(this); diff --git a/core/src/test/java/org/elasticsearch/search/MultiValueModeTests.java b/core/src/test/java/org/elasticsearch/search/MultiValueModeTests.java index 1a357c55eb0..df18b00528c 100644 --- a/core/src/test/java/org/elasticsearch/search/MultiValueModeTests.java +++ b/core/src/test/java/org/elasticsearch/search/MultiValueModeTests.java @@ -41,7 +41,6 @@ import org.elasticsearch.index.fielddata.FieldData; import org.elasticsearch.index.fielddata.NumericDoubleValues; import org.elasticsearch.index.fielddata.SortedBinaryDocValues; import org.elasticsearch.index.fielddata.SortedNumericDoubleValues; -import org.elasticsearch.search.MultiValueMode.UnsortedNumericDoubleValues; import org.elasticsearch.test.ESTestCase; import java.io.IOException; @@ -92,7 +91,7 @@ public class MultiValueModeTests extends ESTestCase { docsWithValue.set(i); } } - + final Supplier multiValues = () -> DocValues.singleton(new AbstractNumericDocValues() { int docId = -1; @Override @@ -711,126 +710,6 @@ public class MultiValueModeTests extends ESTestCase { } } - public void testUnsortedSingleValuedDoubles() throws Exception { - final int numDocs = scaledRandomIntBetween(1, 100); - final double[] array = new double[numDocs]; - final FixedBitSet docsWithValue = randomBoolean() ? null : new FixedBitSet(numDocs); - for (int i = 0; i < array.length; ++i) { - if (randomBoolean()) { - array[i] = randomDouble(); - if (docsWithValue != null) { - docsWithValue.set(i); - } - } else if (docsWithValue != null && randomBoolean()) { - docsWithValue.set(i); - } - } - final NumericDoubleValues singleValues = new NumericDoubleValues() { - private int docID; - @Override - public boolean advanceExact(int doc) throws IOException { - docID = doc; - return docsWithValue == null || docsWithValue.get(docID); - } - @Override - public double doubleValue() { - return array[docID]; - } - }; - final SortedNumericDoubleValues singletonValues = FieldData.singleton(singleValues); - final MultiValueMode.UnsortedNumericDoubleValues multiValues = new MultiValueMode.UnsortedNumericDoubleValues() { - - @Override - public int docValueCount() { - return singletonValues.docValueCount(); - } - - @Override - public boolean advanceExact(int doc) throws IOException { - return singletonValues.advanceExact(doc); - } - - @Override - public double nextValue() throws IOException { - return Math.cos(singletonValues.nextValue()); - } - }; - verifyUnsortedNumeric(() -> multiValues, numDocs); - } - - public void testUnsortedMultiValuedDoubles() throws Exception { - final int numDocs = scaledRandomIntBetween(1, 100); - final double[][] array = new double[numDocs][]; - for (int i = 0; i < numDocs; ++i) { - final double[] values = new double[randomInt(4)]; - for (int j = 0; j < values.length; ++j) { - values[j] = randomDouble(); - } - Arrays.sort(values); - array[i] = values; - } - final MultiValueMode.UnsortedNumericDoubleValues multiValues = new MultiValueMode.UnsortedNumericDoubleValues() { - int doc; - int i; - - @Override - public int docValueCount() { - return array[doc].length; - } - - @Override - public boolean advanceExact(int doc) { - this.doc = doc; - i = 0; - return array[doc].length > 0; - } - - @Override - public double nextValue() { - return Math.sin(array[doc][i++]); - } - }; - verifyUnsortedNumeric(() -> multiValues, numDocs); - } - - private void verifyUnsortedNumeric(Supplier supplier, int maxDoc) throws IOException { - for (double missingValue : new double[] { 0, randomDouble() }) { - for (MultiValueMode mode : new MultiValueMode[] {MultiValueMode.MIN, MultiValueMode.MAX, MultiValueMode.SUM, MultiValueMode.AVG}) { - UnsortedNumericDoubleValues values = supplier.get(); - final NumericDoubleValues selected = mode.select(values, missingValue); - for (int i = 0; i < maxDoc; ++i) { - assertTrue(selected.advanceExact(i)); - final double actual = selected.doubleValue(); - double expected = 0.0; - if (values.advanceExact(i) == false) { - expected = missingValue; - } else { - int numValues = values.docValueCount(); - if (mode == MultiValueMode.MAX) { - expected = Long.MIN_VALUE; - } else if (mode == MultiValueMode.MIN) { - expected = Long.MAX_VALUE; - } - for (int j = 0; j < numValues; ++j) { - if (mode == MultiValueMode.SUM || mode == MultiValueMode.AVG) { - expected += values.nextValue(); - } else if (mode == MultiValueMode.MIN) { - expected = Math.min(expected, values.nextValue()); - } else if (mode == MultiValueMode.MAX) { - expected = Math.max(expected, values.nextValue()); - } - } - if (mode == MultiValueMode.AVG) { - expected = expected/numValues; - } - } - - assertEquals(mode.toString() + " docId=" + i, expected, actual, 0.1); - } - } - } - } - public void testValidOrdinals() { assertThat(MultiValueMode.SUM.ordinal(), equalTo(0)); assertThat(MultiValueMode.AVG.ordinal(), equalTo(1));