Cleanup ScriptDocValues. This commit adds a getValues method to all ScriptDocValues for easy access

in scripts via doc['field'].values / value.
This commit is contained in:
Simon Willnauer 2013-04-03 14:10:49 +02:00
parent 4f96b36376
commit d758401add
16 changed files with 1074 additions and 129 deletions

View File

@ -0,0 +1,163 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.common.util;
import java.util.AbstractList;
import java.util.RandomAccess;
import org.apache.lucene.util.ArrayUtil;
import com.google.common.primitives.Doubles;
public final class SlicedDoubleList extends AbstractList<Double> implements RandomAccess {
public static final SlicedDoubleList EMPTY = new SlicedDoubleList(0);
public double[] values;
public int offset;
public int length;
public SlicedDoubleList(int capacity) {
this(new double[capacity], 0, capacity);
}
public SlicedDoubleList(double[] values, int offset, int length) {
this.values = values;
this.offset = offset;
this.length = length;
}
@Override
public int size() {
return length;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public Double get(int index) {
assert index < size();
return values[offset + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Double)
&& indexOf(values, (Double) target, offset, offset+length) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Double) {
int i = indexOf(values, (Double) target, offset, offset+length);
if (i >= 0) {
return i - offset;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Double) {
int i = lastIndexOf(values, (Double) target, offset, offset+length);
if (i >= 0) {
return i - offset;
}
}
return -1;
}
@Override
public Double set(int index, Double element) {
throw new UnsupportedOperationException("modifying list opertations are not implemented");
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof SlicedDoubleList) {
SlicedDoubleList that = (SlicedDoubleList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (values[offset + i] != that.values[that.offset + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = 0; i < length; i++) {
result = 31 * result + Doubles.hashCode(values[offset+i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 10);
builder.append('[');
if (length > 0) {
builder.append(values[offset]);
for (int i = 1; i < length; i++) {
builder.append(", ").append(values[offset+i]);
}
}
return builder.append(']').toString();
}
private static int indexOf(double[] array, double target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
private static int lastIndexOf(double[] array, double target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
public void grow(int newLength) {
assert offset == 0;
values = ArrayUtil.grow(values, newLength);
}
}

View File

@ -0,0 +1,164 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.common.util;
import java.util.AbstractList;
import java.util.RandomAccess;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.LongsRef;
import com.google.common.primitives.Longs;
public class SlicedLongList extends AbstractList<Long> implements RandomAccess {
public static final SlicedLongList EMPTY = new SlicedLongList(LongsRef.EMPTY_LONGS, 0, 0);
public long[] values;
public int offset;
public int length;
public SlicedLongList(int capacity) {
this(new long[capacity], 0, capacity);
}
public SlicedLongList(long[] values, int offset, int length) {
this.values = values;
this.offset = offset;
this.length = length;
}
@Override
public int size() {
return length;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public Long get(int index) {
assert index < size();
return values[offset + index];
}
@Override
public boolean contains(Object target) {
// Overridden to prevent a ton of boxing
return (target instanceof Long)
&& indexOf(values, (Long) target, offset, offset+length) != -1;
}
@Override
public int indexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Long) {
int i = indexOf(values, (Long) target, offset, offset+length);
if (i >= 0) {
return i - offset;
}
}
return -1;
}
@Override
public int lastIndexOf(Object target) {
// Overridden to prevent a ton of boxing
if (target instanceof Long) {
int i = lastIndexOf(values, (Long) target, offset, offset+length);
if (i >= 0) {
return i - offset;
}
}
return -1;
}
@Override
public Long set(int index, Long element) {
throw new UnsupportedOperationException("modifying list opertations are not implemented");
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof SlicedLongList) {
SlicedLongList that = (SlicedLongList) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (values[offset + i] != that.values[that.offset + i]) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = 0; i < length; i++) {
result = 31 * result + Longs.hashCode(values[offset+i]);
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 10);
builder.append('[');
if (length > 0) {
builder.append(values[offset]);
for (int i = 1; i < length; i++) {
builder.append(", ").append(values[offset+i]);
}
}
return builder.append(']').toString();
}
private static int indexOf(long[] array, long target, int start, int end) {
for (int i = start; i < end; i++) {
if (array[i] == target) {
return i;
}
}
return -1;
}
private static int lastIndexOf(long[] array, long target, int start, int end) {
for (int i = end - 1; i >= start; i--) {
if (array[i] == target) {
return i;
}
}
return -1;
}
public void grow(int newLength) {
assert offset == 0;
values = ArrayUtil.grow(values, newLength);
}
}

View File

@ -0,0 +1,106 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.common.util;
import java.util.AbstractList;
import java.util.RandomAccess;
// TODO this could use some javadocs
public abstract class SlicedObjectList<T> extends AbstractList<T> implements RandomAccess {
public T[] values;
public int offset;
public int length;
public SlicedObjectList(T[] values) {
this(values, 0, values.length);
}
public SlicedObjectList(T[] values, int offset, int length) {
this.values = values;
this.offset = offset;
this.length = length;
}
@Override
public int size() {
return length;
}
@Override
public boolean isEmpty() {
return size() == 0;
}
@Override
public T get(int index) {
assert index < size();
return values[offset + index];
}
@Override
public T set(int index, T element) {
throw new UnsupportedOperationException("modifying list opertations are not implemented");
}
@Override
public boolean equals(Object object) {
if (object == this) {
return true;
}
if (object instanceof SlicedObjectList) {
SlicedObjectList<?> that = (SlicedObjectList<?>) object;
int size = size();
if (that.size() != size) {
return false;
}
for (int i = 0; i < size; i++) {
if (values[offset + i].equals(that.values[that.offset + i])) {
return false;
}
}
return true;
}
return super.equals(object);
}
@Override
public int hashCode() {
int result = 1;
for (int i = 0; i < length; i++) {
result = 31 * result + values[offset+i].hashCode();
}
return result;
}
@Override
public String toString() {
StringBuilder builder = new StringBuilder(size() * 10);
builder.append('[');
if (length > 0) {
builder.append(values[offset]);
for (int i = 1; i < length; i++) {
builder.append(", ").append(values[offset+i]);
}
}
return builder.append(']').toString();
}
public abstract void grow(int newLength);
}

View File

@ -23,7 +23,7 @@ import org.apache.lucene.util.BytesRef;
/**
*/
public abstract class AtomicNumericFieldData<Script extends ScriptDocValues> implements AtomicFieldData<Script> {
public abstract class AtomicNumericFieldData implements AtomicFieldData<ScriptDocValues> {
private boolean isFloat;
@ -35,10 +35,20 @@ public abstract class AtomicNumericFieldData<Script extends ScriptDocValues> imp
public abstract DoubleValues getDoubleValues();
@Override
public ScriptDocValues getScriptValues() {
if (isFloat) {
return new ScriptDocValues.NumericDouble(getDoubleValues());
} else {
return new ScriptDocValues.NumericLong(getLongValues());
}
}
@Override
public BytesValues getBytesValues() {
if (isFloat) {
final DoubleValues values = getDoubleValues();
final DoubleValues values = getDoubleValues();
return new BytesValues(values.isMultiValued()) {
@Override

View File

@ -19,28 +19,44 @@
package org.elasticsearch.index.fielddata;
import java.util.Collections;
import java.util.List;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.BytesRef;
import org.apache.lucene.util.CharsRef;
import org.apache.lucene.util.RamUsageEstimator;
import org.apache.lucene.util.UnicodeUtil;
import org.elasticsearch.common.geo.GeoDistance;
import org.elasticsearch.common.geo.GeoPoint;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.util.SlicedDoubleList;
import org.elasticsearch.common.util.SlicedLongList;
import org.elasticsearch.common.util.SlicedObjectList;
import org.elasticsearch.index.fielddata.BytesValues.Iter;
import org.joda.time.MutableDateTime;
/**
* Script level doc values, the assumption is that any implementation will implement a <code>getValue</code>
* and a <code>getValues</code> that return the relevant type that then can be used in scripts.
*/
public interface ScriptDocValues {
public abstract class ScriptDocValues {
static final ScriptDocValues EMPTY = new Empty();
static final Strings EMPTY_STRINGS = new Strings(BytesValues.EMPTY);
public static final ScriptDocValues EMPTY = new Empty();
public static final Strings EMPTY_STRINGS = new Strings(BytesValues.EMPTY);
protected int docId;
protected boolean listLoaded = false;
void setNextDocId(int docId);
public void setNextDocId(int docId) {
this.docId = docId;
this.listLoaded = false;
}
boolean isEmpty();
public abstract boolean isEmpty();
public abstract List<?> getValues();
static class Empty implements ScriptDocValues {
public static class Empty extends ScriptDocValues {
@Override
public void setNextDocId(int docId) {
}
@ -49,21 +65,35 @@ public interface ScriptDocValues {
public boolean isEmpty() {
return true;
}
@Override
public List<?> getValues() {
return Collections.emptyList();
}
}
static class Strings implements ScriptDocValues {
public final static class Strings extends ScriptDocValues {
private final BytesValues values;
private final CharsRef spare = new CharsRef();
private int docId;
private SlicedObjectList<String> list;
public Strings(BytesValues values) {
this.values = values;
}
list = new SlicedObjectList<String>(values.isMultiValued() ? new String[10] : new String[1]) {
@Override
public void setNextDocId(int docId) {
this.docId = docId;
@Override
public void grow(int newLength) {
assert offset == 0; // NOTE: senseless if offset != 0
if (values.length >= newLength) {
return;
}
final String[] current = values;
values = new String[ArrayUtil.oversize(newLength, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
System.arraycopy(current, 0, values, 0, current.length);
}
};
}
@Override
@ -79,24 +109,35 @@ public interface ScriptDocValues {
}
return null;
}
public List<String> getValues() {
if (!listLoaded) {
list.offset = 0;
list.length = 0;
Iter iter = values.getIter(docId);
while(iter.hasNext()) {
BytesRef next = iter.next();
UnicodeUtil.UTF8toUTF16(next, spare);
list.values[list.length++] = spare.toString();
}
listLoaded = true;
}
return list;
}
}
static class NumericLong implements ScriptDocValues {
public static class NumericLong extends ScriptDocValues {
private final LongValues values;
private final MutableDateTime date = new MutableDateTime(0);
private int docId;
private final SlicedLongList list;
public NumericLong(LongValues values) {
this.values = values;
}
@Override
public void setNextDocId(int docId) {
this.docId = docId;
this.list = new SlicedLongList(values.isMultiValued() ? 10 : 1);
}
@Override
@ -107,6 +148,20 @@ public interface ScriptDocValues {
public long getValue() {
return values.getValue(docId);
}
public List<Long> getValues() {
if (!listLoaded) {
final LongValues.Iter iter = values.getIter(docId);
list.offset = 0;
list.length = 0;
while(iter.hasNext()) {
list.grow(list.length+1);
list.values[list.length++] = iter.next();
}
listLoaded = true;
}
return list;
}
public MutableDateTime getDate() {
date.setMillis(getValue());
@ -114,18 +169,15 @@ public interface ScriptDocValues {
}
}
static class NumericDouble implements ScriptDocValues {
public static class NumericDouble extends ScriptDocValues {
private final DoubleValues values;
private int docId;
private final SlicedDoubleList list;
public NumericDouble(DoubleValues values) {
this.values = values;
}
this.list = new SlicedDoubleList(values.isMultiValued() ? 10 : 1);
@Override
public void setNextDocId(int docId) {
this.docId = docId;
}
@Override
@ -136,21 +188,44 @@ public interface ScriptDocValues {
public double getValue() {
return values.getValue(docId);
}
public List<Double> getValues() {
if (!listLoaded) {
final DoubleValues.Iter iter = values.getIter(docId);
list.offset = 0;
list.length = 0;
while(iter.hasNext()) {
list.grow(list.length+1);
list.values[list.length++] = iter.next();
}
listLoaded = true;
}
return list;
}
}
static class GeoPoints implements ScriptDocValues {
public static class GeoPoints extends ScriptDocValues {
private final GeoPointValues values;
private int docId;
private final SlicedObjectList<GeoPoint> list;
public GeoPoints(GeoPointValues values) {
this.values = values;
list = new SlicedObjectList<GeoPoint>(values.isMultiValued() ? new GeoPoint[10] : new GeoPoint[1]) {
@Override
public void grow(int newLength) {
assert offset == 0; // NOTE: senseless if offset != 0
if (values.length >= newLength) {
return;
}
final GeoPoint[] current = values;
values = new GeoPoint[ArrayUtil.oversize(newLength, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
System.arraycopy(current, 0, values, 0, current.length);
}
};
}
@Override
public void setNextDocId(int docId) {
this.docId = docId;
}
@Override
public boolean isEmpty() {
@ -160,6 +235,28 @@ public interface ScriptDocValues {
public GeoPoint getValue() {
return values.getValue(docId);
}
public List<GeoPoint> getValues() {
if (!listLoaded) {
GeoPointValues.Iter iter = values.getIter(docId);
list.offset = 0;
list.length = 0;
while(iter.hasNext()) {
int index = list.length;
list.grow(index+1);
GeoPoint next = iter.next();
GeoPoint point = list.values[index];
if (point == null) {
point = list.values[index] = new GeoPoint();
}
point.reset(next.lat(), next.lon());
list.values[list.length++] = point;
}
listLoaded = true;
}
return list;
}
public double factorDistance(double lat, double lon) {
GeoPoint point = getValue();

View File

@ -124,10 +124,7 @@ public abstract class ByteArrayAtomicFieldData extends AtomicNumericFieldData {
}
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, ordinals.ordinals());
@ -203,11 +200,6 @@ public abstract class ByteArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, set);
@ -296,12 +288,6 @@ public abstract class ByteArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values);

View File

@ -124,11 +124,6 @@ public abstract class DoubleArrayAtomicFieldData extends AtomicNumericFieldData
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericDouble(getDoubleValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, ordinals.ordinals());
@ -202,11 +197,6 @@ public abstract class DoubleArrayAtomicFieldData extends AtomicNumericFieldData
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericDouble(getDoubleValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, set);
@ -294,12 +284,6 @@ public abstract class DoubleArrayAtomicFieldData extends AtomicNumericFieldData
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericDouble(getDoubleValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values);

View File

@ -123,11 +123,6 @@ public abstract class FloatArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericDouble(getDoubleValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, ordinals.ordinals());
@ -200,12 +195,6 @@ public abstract class FloatArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericDouble(getDoubleValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, set);
@ -295,11 +284,6 @@ public abstract class FloatArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericDouble(getDoubleValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values);

View File

@ -30,7 +30,7 @@ import org.elasticsearch.index.fielddata.ordinals.Ordinals;
/**
*/
public abstract class GeoPointDoubleArrayAtomicFieldData extends AtomicGeoPointFieldData {
public abstract class GeoPointDoubleArrayAtomicFieldData extends AtomicGeoPointFieldData<ScriptDocValues> {
public static final GeoPointDoubleArrayAtomicFieldData EMPTY = new Empty();

View File

@ -123,11 +123,6 @@ public abstract class IntArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, ordinals.ordinals());
@ -202,11 +197,6 @@ public abstract class IntArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, set);
@ -294,11 +284,6 @@ public abstract class IntArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values);

View File

@ -123,11 +123,6 @@ public abstract class LongArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, ordinals.ordinals());
@ -202,11 +197,6 @@ public abstract class LongArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, set);
@ -294,11 +284,6 @@ public abstract class LongArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values);

View File

@ -123,11 +123,6 @@ public abstract class ShortArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, ordinals.ordinals());
@ -202,11 +197,6 @@ public abstract class ShortArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values, set);
@ -293,17 +283,11 @@ public abstract class ShortArrayAtomicFieldData extends AtomicNumericFieldData {
return size;
}
@Override
public ScriptDocValues getScriptValues() {
return new ScriptDocValues.NumericLong(getLongValues());
}
@Override
public LongValues getLongValues() {
return new LongValues(values);
}
@Override
public DoubleValues getDoubleValues() {
return new DoubleValues(values);

View File

@ -20,6 +20,7 @@
package org.elasticsearch.test.integration.search.sort;
import org.elasticsearch.ElasticSearchException;
import org.elasticsearch.action.index.IndexRequestBuilder;
import org.elasticsearch.action.search.SearchPhaseExecutionException;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
@ -429,6 +430,101 @@ public class SimpleSortTests extends AbstractNodesTests {
assertThat(searchResponse.toString(), not(containsString("error")));
}
@Test
public void testSortMinValueScript() throws IOException {
try {
client.admin().indices().prepareDelete("test").execute().actionGet();
} catch (Exception e) {
// ignore
}
String mapping = jsonBuilder().startObject().startObject("type1").startObject("properties")
.startObject("lvalue").field("type", "long").endObject()
.startObject("dvalue").field("type", "double").endObject()
.startObject("svalue").field("type", "string").endObject()
.startObject("gvalue").field("type", "geo_point").endObject()
.endObject().endObject().endObject().string();
client.admin().indices().prepareCreate("test").addMapping("type1", mapping).execute().actionGet();
client.admin().cluster().prepareHealth().setWaitForEvents(Priority.LANGUID).setWaitForGreenStatus().execute().actionGet();
for (int i = 0; i < 10; i++) {
IndexRequestBuilder req = client.prepareIndex("test", "type1", ""+i).setSource(jsonBuilder().startObject()
.field("ord", i)
.field("svalue", new String[]{""+i, ""+(i+1), ""+(i+2)})
.field("lvalue", new long[] {i, i+1, i+2})
.field("dvalue", new double[] {i, i+1, i+2})
.startObject("gvalue")
.startObject("location")
.field("lat", (double)i+1)
.field("lon", (double)i)
.endObject()
.endObject()
.endObject());
req.execute().actionGet();
}
for (int i = 10; i < 20; i++) { // add some docs that don't have values in those fields
client.prepareIndex("test", "type1", ""+i).setSource(jsonBuilder().startObject()
.field("ord", i)
.endObject()).execute().actionGet();
}
client.admin().indices().prepareRefresh("test").execute().actionGet();
// test the long values
SearchResponse searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("min", "var retval = Long.MAX_VALUE; for (v : doc['lvalue'].values){ retval = Math.min(v, retval);} return retval;")
.addSort("ord", SortOrder.ASC).setSize(10)
.execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().getTotalHits(), equalTo(20l));
for (int i = 0; i < 10; i++) {
assertThat("res: " + i + " id: " + searchResponse.getHits().getAt(i).getId(), (Long)searchResponse.getHits().getAt(i).field("min").value(), equalTo((long)i));
}
// test the double values
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("min", "var retval = Double.MAX_VALUE; for (v : doc['dvalue'].values){ retval = Math.min(v, retval);} return retval;")
.addSort("ord", SortOrder.ASC).setSize(10)
.execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().getTotalHits(), equalTo(20l));
for (int i = 0; i < 10; i++) {
assertThat("res: " + i + " id: " + searchResponse.getHits().getAt(i).getId(), (Double)searchResponse.getHits().getAt(i).field("min").value(), equalTo((double)i));
}
// test the string values
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("min", "var retval = Integer.MAX_VALUE; for (v : doc['svalue'].values){ retval = Math.min(Integer.parseInt(v), retval);} return retval;")
.addSort("ord", SortOrder.ASC).setSize(10)
.execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().getTotalHits(), equalTo(20l));
for (int i = 0; i < 10; i++) {
assertThat("res: " + i + " id: " + searchResponse.getHits().getAt(i).getId(), (Integer)searchResponse.getHits().getAt(i).field("min").value(), equalTo(i));
}
// test the geopoint values
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("min", "var retval = Double.MAX_VALUE; for (v : doc['gvalue'].values){ retval = Math.min(v.lon, retval);} return retval;")
.addSort("ord", SortOrder.ASC).setSize(10)
.execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().getTotalHits(), equalTo(20l));
for (int i = 0; i < 10; i++) {
assertThat("res: " + i + " id: " + searchResponse.getHits().getAt(i).getId(), (Double)searchResponse.getHits().getAt(i).field("min").value(), equalTo((double)i));
}
}
@Test
public void testDocumentsWithNullValue() throws Exception {
@ -472,6 +568,19 @@ public class SimpleSortTests extends AbstractNodesTests {
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().getTotalHits(), equalTo(3l));
assertThat((String) searchResponse.getHits().getAt(0).field("id").value(), equalTo("2"));
assertThat((String) searchResponse.getHits().getAt(1).field("id").value(), equalTo("1"));
assertThat((String) searchResponse.getHits().getAt(2).field("id").value(), equalTo("3"));
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].values[0]")
.addSort("svalue", SortOrder.ASC)
.execute().actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.getShardFailures()), searchResponse.getShardFailures().length, equalTo(0));
assertThat(searchResponse.getHits().getTotalHits(), equalTo(3l));
assertThat((String) searchResponse.getHits().getAt(0).field("id").value(), equalTo("2"));
assertThat((String) searchResponse.getHits().getAt(1).field("id").value(), equalTo("1"));

View File

@ -0,0 +1,120 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.test.unit.common.util;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import org.elasticsearch.common.util.SlicedDoubleList;
import org.testng.annotations.Test;
/**
* Tests for {@link SlicedDoubleList}
*/
public class SlicedDoubleListTests {
@Test
public void testCapacity() {
SlicedDoubleList list = new SlicedDoubleList(5);
assertThat(list.length, equalTo(5));
assertThat(list.offset, equalTo(0));
assertThat(list.values.length, equalTo(5));
assertThat(list.size(), equalTo(5));
list = new SlicedDoubleList(new double[10], 5, 5);
assertThat(list.length, equalTo(5));
assertThat(list.offset, equalTo(5));
assertThat(list.size(), equalTo(5));
assertThat(list.values.length, equalTo(10));
}
@Test
public void testGrow() {
SlicedDoubleList list = new SlicedDoubleList(5);
list.length = 1000;
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((double)i);
}
int expected = 0;
for (Double d : list) {
assertThat((double)expected++, equalTo(d));
}
for (int i = 0; i < list.length; i++) {
assertThat((double)i, equalTo(list.get(i)));
}
int count = 0;
for (int i = list.offset; i < list.offset+list.length; i++) {
assertThat((double)count++, equalTo(list.values[i]));
}
}
@Test
public void testIndexOf() {
SlicedDoubleList list = new SlicedDoubleList(5);
list.length = 1000;
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((double)i%100);
}
assertThat(999, equalTo(list.lastIndexOf(99.0d)));
assertThat(99, equalTo(list.indexOf(99.0d)));
assertThat(-1, equalTo(list.lastIndexOf(100.0d)));
assertThat(-1, equalTo(list.indexOf(100.0d)));
}
public void testIsEmpty() {
SlicedDoubleList list = new SlicedDoubleList(5);
assertThat(false, equalTo(list.isEmpty()));
list.length = 0;
assertThat(true, equalTo(list.isEmpty()));
}
@Test
public void testSet() {
SlicedDoubleList list = new SlicedDoubleList(5);
try {
list.set(0, (double)4);
assert false;
} catch (UnsupportedOperationException ex) {
}
try {
list.add((double)4);
assert false;
} catch (UnsupportedOperationException ex) {
}
}
@Test
public void testToString() {
SlicedDoubleList list = new SlicedDoubleList(5);
assertThat("[0.0, 0.0, 0.0, 0.0, 0.0]", equalTo(list.toString()));
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((double)i);
}
assertThat("[0.0, 1.0, 2.0, 3.0, 4.0]", equalTo(list.toString()));
}
}

View File

@ -0,0 +1,120 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.test.unit.common.util;
import org.elasticsearch.common.util.SlicedDoubleList;
import org.elasticsearch.common.util.SlicedLongList;
import org.testng.annotations.Test;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
/**
* Tests for {@link SlicedLongList}
*/
public class SlicedLongListTests {
@Test
public void testCapacity() {
SlicedLongList list = new SlicedLongList(5);
assertThat(list.length, equalTo(5));
assertThat(list.offset, equalTo(0));
assertThat(list.values.length, equalTo(5));
assertThat(list.size(), equalTo(5));
list = new SlicedLongList(new long[10], 5, 5);
assertThat(list.length, equalTo(5));
assertThat(list.offset, equalTo(5));
assertThat(list.size(), equalTo(5));
assertThat(list.values.length, equalTo(10));
}
@Test
public void testGrow() {
SlicedLongList list = new SlicedLongList(5);
list.length = 1000;
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((long)i);
}
int expected = 0;
for (Long d : list) {
assertThat((long)expected++, equalTo(d));
}
for (int i = 0; i < list.length; i++) {
assertThat((long)i, equalTo(list.get(i)));
}
int count = 0;
for (int i = list.offset; i < list.offset+list.length; i++) {
assertThat((long)count++, equalTo(list.values[i]));
}
}
@Test
public void testSet() {
SlicedLongList list = new SlicedLongList(5);
try {
list.set(0, (long)4);
assert false;
} catch (UnsupportedOperationException ex) {
}
try {
list.add((long)4);
assert false;
} catch (UnsupportedOperationException ex) {
}
}
@Test
public void testIndexOf() {
SlicedLongList list = new SlicedLongList(5);
list.length = 1000;
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((long)i%100);
}
assertThat(999, equalTo(list.lastIndexOf(99l)));
assertThat(99, equalTo(list.indexOf(99l)));
assertThat(-1, equalTo(list.lastIndexOf(100l)));
assertThat(-1, equalTo(list.indexOf(100l)));
}
public void testIsEmpty() {
SlicedLongList list = new SlicedLongList(5);
assertThat(false, equalTo(list.isEmpty()));
list.length = 0;
assertThat(true, equalTo(list.isEmpty()));
}
@Test
public void testToString() {
SlicedLongList list = new SlicedLongList(5);
assertThat("[0, 0, 0, 0, 0]", equalTo(list.toString()));
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((long)i);
}
assertThat("[0, 1, 2, 3, 4]", equalTo(list.toString()));
}
}

View File

@ -0,0 +1,148 @@
/*
* Licensed to ElasticSearch and Shay Banon 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.test.unit.common.util;
import static org.hamcrest.MatcherAssert.assertThat;
import static org.hamcrest.Matchers.equalTo;
import org.apache.lucene.util.ArrayUtil;
import org.apache.lucene.util.RamUsageEstimator;
import org.elasticsearch.common.util.SlicedObjectList;
import org.testng.annotations.Test;
/**
* Tests for {@link SlicedObjectList}
*/
public class SlicedObjectListTests {
public class TestList extends SlicedObjectList<Double> {
public TestList(int capactiy) {
this(new Double[capactiy], 0, capactiy);
}
public TestList(Double[] values, int offset, int length) {
super(values, offset, length);
}
public TestList(Double[] values) {
super(values);
}
@Override
public void grow(int newLength) {
assert offset == 0; // NOTE: senseless if offset != 0
if (values.length >= newLength) {
return;
}
final Double[] current = values;
values = new Double[ArrayUtil.oversize(newLength, RamUsageEstimator.NUM_BYTES_OBJECT_REF)];
System.arraycopy(current, 0, values, 0, current.length);
}
}
@Test
public void testCapacity() {
TestList list = new TestList(5);
assertThat(list.length, equalTo(5));
assertThat(list.offset, equalTo(0));
assertThat(list.values.length, equalTo(5));
assertThat(list.size(), equalTo(5));
list = new TestList(new Double[10], 5, 5);
assertThat(list.length, equalTo(5));
assertThat(list.offset, equalTo(5));
assertThat(list.size(), equalTo(5));
assertThat(list.values.length, equalTo(10));
}
@Test
public void testGrow() {
TestList list = new TestList(5);
list.length = 1000;
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((double)i);
}
int expected = 0;
for (Double d : list) {
assertThat((double)expected++, equalTo(d));
}
for (int i = 0; i < list.length; i++) {
assertThat((double)i, equalTo(list.get(i)));
}
int count = 0;
for (int i = list.offset; i < list.offset+list.length; i++) {
assertThat((double)count++, equalTo(list.values[i]));
}
}
@Test
public void testIndexOf() {
TestList list = new TestList(5);
list.length = 1000;
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((double)i%100);
}
assertThat(999, equalTo(list.lastIndexOf(99.0d)));
assertThat(99, equalTo(list.indexOf(99.0d)));
assertThat(-1, equalTo(list.lastIndexOf(100.0d)));
assertThat(-1, equalTo(list.indexOf(100.0d)));
}
public void testIsEmpty() {
TestList list = new TestList(5);
assertThat(false, equalTo(list.isEmpty()));
list.length = 0;
assertThat(true, equalTo(list.isEmpty()));
}
@Test
public void testSet() {
TestList list = new TestList(5);
try {
list.set(0, (double)4);
assert false;
} catch (UnsupportedOperationException ex) {
}
try {
list.add((double)4);
assert false;
} catch (UnsupportedOperationException ex) {
}
}
@Test
public void testToString() {
TestList list = new TestList(5);
assertThat("[null, null, null, null, null]", equalTo(list.toString()));
for (int i = 0; i < list.length; i++) {
list.grow(i+1);
list.values[i] = ((double)i);
}
assertThat("[0.0, 1.0, 2.0, 3.0, 4.0]", equalTo(list.toString()));
}
}