add geo distance sort option, refactor java level sort API to have sort builders (similar to facets)

This commit is contained in:
kimchy 2010-08-08 21:46:11 +03:00
parent 8b19d353c1
commit ff8d743337
20 changed files with 798 additions and 205 deletions

View File

@ -33,8 +33,9 @@ import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.facets.AbstractFacetBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortOrder;
import javax.annotation.Nullable;
import java.util.Map;
/**
@ -262,32 +263,18 @@ public class SearchRequestBuilder extends BaseRequestBuilder<SearchRequest, Sear
* @param field The name of the field
* @param order The sort ordering
*/
public SearchRequestBuilder addSort(String field, SearchSourceBuilder.Order order) {
public SearchRequestBuilder addSort(String field, SortOrder order) {
sourceBuilder().sort(field, order);
return this;
}
/**
* Adds a sort script.
* Adds a generic sort builder.
*
* @param script The script to execute.
* @param type The type of the result (can either be "string" or "number").
* @param order The order.
* @see org.elasticsearch.search.sort.SortBuilders
*/
public SearchRequestBuilder addSortScript(String script, String type, SearchSourceBuilder.Order order) {
return addSortScript(script, type, order, null);
}
/**
* Adds a sort script.
*
* @param script The script to execute.
* @param type The type of the result (can either be "string" or "number").
* @param order The order.
* @param params Optional parameters to the script.
*/
public SearchRequestBuilder addSortScript(String script, String type, SearchSourceBuilder.Order order, @Nullable Map<String, Object> params) {
sourceBuilder().sortScript(script, type, order, params);
public SearchRequestBuilder addSort(SortBuilder sort) {
sourceBuilder().sort(sort);
return this;
}

View File

@ -0,0 +1,183 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.lucene.geo;
import org.apache.lucene.index.IndexReader;
import org.apache.lucene.search.FieldComparator;
import org.apache.lucene.search.FieldComparatorSource;
import org.elasticsearch.ElasticSearchIllegalArgumentException;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.index.cache.field.data.FieldDataCache;
import org.elasticsearch.index.field.data.FieldData;
import org.elasticsearch.index.field.data.NumericFieldData;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.MapperService;
import org.elasticsearch.index.mapper.xcontent.XContentGeoPointFieldMapper;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
// LUCENE MONITOR: Monitor against FieldComparator.Double
public class GeoDistanceDataComparator extends FieldComparator {
public static FieldComparatorSource comparatorSource(String fieldName, double lat, double lon, DistanceUnit unit, GeoDistance geoDistance,
FieldDataCache fieldDataCache, MapperService mapperService) {
return new InnerSource(fieldName, lat, lon, unit, geoDistance, fieldDataCache, mapperService);
}
private static class InnerSource extends FieldComparatorSource {
protected final String fieldName;
protected final double lat;
protected final double lon;
protected final DistanceUnit unit;
protected final GeoDistance geoDistance;
protected final FieldDataCache fieldDataCache;
private final MapperService mapperService;
private InnerSource(String fieldName, double lat, double lon, DistanceUnit unit, GeoDistance geoDistance,
FieldDataCache fieldDataCache, MapperService mapperService) {
this.fieldName = fieldName;
this.lat = lat;
this.lon = lon;
this.unit = unit;
this.geoDistance = geoDistance;
this.fieldDataCache = fieldDataCache;
this.mapperService = mapperService;
}
@Override public FieldComparator newComparator(String fieldname, int numHits, int sortPos, boolean reversed) throws IOException {
return new GeoDistanceDataComparator(numHits, fieldname, lat, lon, unit, geoDistance, fieldDataCache, mapperService);
}
}
protected final String fieldName;
protected final String indexLatFieldName;
protected final String indexLonFieldName;
protected final double lat;
protected final double lon;
protected final DistanceUnit unit;
protected final GeoDistance geoDistance;
protected final FieldDataCache fieldDataCache;
protected final FieldData.Type fieldDataType;
protected NumericFieldData latFieldData;
protected NumericFieldData lonFieldData;
private final double[] values;
private double bottom;
public GeoDistanceDataComparator(int numHits, String fieldName, double lat, double lon, DistanceUnit unit, GeoDistance geoDistance,
FieldDataCache fieldDataCache, MapperService mapperService) {
values = new double[numHits];
this.fieldName = fieldName;
this.lat = lat;
this.lon = lon;
this.unit = unit;
this.geoDistance = geoDistance;
this.fieldDataCache = fieldDataCache;
FieldMapper mapper = mapperService.smartNameFieldMapper(fieldName + XContentGeoPointFieldMapper.Names.LAT_SUFFIX);
if (mapper == null) {
throw new ElasticSearchIllegalArgumentException("No mapping found for field [" + fieldName + "] for geo distance sort");
}
this.indexLatFieldName = mapper.names().indexName();
mapper = mapperService.smartNameFieldMapper(fieldName + XContentGeoPointFieldMapper.Names.LON_SUFFIX);
if (mapper == null) {
throw new ElasticSearchIllegalArgumentException("No mapping found for field [" + fieldName + "] for geo distance sort");
}
this.indexLonFieldName = mapper.names().indexName();
this.fieldDataType = mapper.fieldDataType();
}
@Override public void setNextReader(IndexReader reader, int docBase) throws IOException {
latFieldData = (NumericFieldData) fieldDataCache.cache(fieldDataType, reader, indexLatFieldName);
lonFieldData = (NumericFieldData) fieldDataCache.cache(fieldDataType, reader, indexLonFieldName);
}
@Override public int compare(int slot1, int slot2) {
final double v1 = values[slot1];
final double v2 = values[slot2];
if (v1 > v2) {
return 1;
} else if (v1 < v2) {
return -1;
} else {
return 0;
}
}
@Override public int compareBottom(int doc) {
double distance;
if (!latFieldData.hasValue(doc) || !lonFieldData.hasValue(doc)) {
// is this true? push this to the "end"
distance = Double.MAX_VALUE;
} else {
distance = geoDistance.calculate(lat, lon, latFieldData.doubleValue(doc), lonFieldData.doubleValue(doc), unit);
}
final double v2 = distance;
if (bottom > v2) {
return 1;
} else if (bottom < v2) {
return -1;
} else {
return 0;
}
}
@Override public void copy(int slot, int doc) {
double distance;
if (!latFieldData.hasValue(doc) || !lonFieldData.hasValue(doc)) {
// is this true? push this to the "end"
distance = Double.MAX_VALUE;
} else {
distance = geoDistance.calculate(lat, lon, latFieldData.doubleValue(doc), lonFieldData.doubleValue(doc), unit);
}
values[slot] = distance;
}
@Override public void setBottom(final int bottom) {
this.bottom = values[bottom];
}
@Override public Comparable value(int slot) {
return Double.valueOf(values[slot]);
}
}

View File

@ -34,6 +34,7 @@ import org.elasticsearch.rest.*;
import org.elasticsearch.rest.action.support.RestActions;
import org.elasticsearch.search.Scroll;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import java.io.IOException;
import java.util.regex.Pattern;
@ -191,11 +192,9 @@ public class RestSearchAction extends BaseRestHandler {
String sortField = sort.substring(0, delimiter);
String reverse = sort.substring(delimiter + 1);
if ("asc".equals(reverse)) {
searchSourceBuilder.sort(sortField, SearchSourceBuilder.Order.ASC);
searchSourceBuilder.sort(sortField, SortOrder.ASC);
} else if ("desc".equals(reverse)) {
searchSourceBuilder.sort(sortField, SearchSourceBuilder.Order.DESC);
} else {
searchSourceBuilder.sort(sortField, reverse.equals("reverse"));
searchSourceBuilder.sort(sortField, SortOrder.DESC);
}
} else {
searchSourceBuilder.sort(sort);

View File

@ -31,16 +31,15 @@ import org.elasticsearch.common.xcontent.builder.XContentBuilder;
import org.elasticsearch.index.query.xcontent.XContentQueryBuilder;
import org.elasticsearch.search.facets.AbstractFacetBuilder;
import org.elasticsearch.search.highlight.HighlightBuilder;
import org.elasticsearch.search.query.SortParseElement;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import javax.annotation.Nullable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import static org.elasticsearch.common.collect.Lists.*;
/**
* A search source builder allowing to easily build search source. Simple construction
* using {@link org.elasticsearch.search.builder.SearchSourceBuilder#searchSource()}.
@ -50,11 +49,6 @@ import static org.elasticsearch.common.collect.Lists.*;
*/
public class SearchSourceBuilder implements ToXContent {
public static enum Order {
ASC,
DESC
}
/**
* A static factory method to construct a new search source.
*/
@ -81,9 +75,7 @@ public class SearchSourceBuilder implements ToXContent {
private Boolean explain;
private List<SortTuple> sortFields;
private List<ScriptSortTuple> sortScripts;
private List<SortBuilder> sorts;
private List<String> fieldNames;
@ -159,18 +151,8 @@ public class SearchSourceBuilder implements ToXContent {
* @param name The name of the field
* @param order The sort ordering
*/
public SearchSourceBuilder sort(String name, Order order) {
boolean reverse = false;
if (name.equals(SortParseElement.SCORE_FIELD_NAME)) {
if (order == Order.ASC) {
reverse = true;
}
} else {
if (order == Order.DESC) {
reverse = true;
}
}
return sort(name, reverse);
public SearchSourceBuilder sort(String name, SortOrder order) {
return sort(SortBuilders.fieldSort(name).order(order));
}
/**
@ -179,36 +161,17 @@ public class SearchSourceBuilder implements ToXContent {
* @param name The name of the field to sort by
*/
public SearchSourceBuilder sort(String name) {
return sort(name, false);
return sort(SortBuilders.fieldSort(name));
}
/**
* Adds a sort script.
*
* @param script The script to execute.
* @param type The type of the result (can either be "string" or "number").
* @param order The order.
* @param params Optional parameters to the script.
* Adds a sort builder.
*/
public SearchSourceBuilder sortScript(String script, String type, Order order, @Nullable Map<String, Object> params) {
if (sortScripts == null) {
sortScripts = Lists.newArrayList();
public SearchSourceBuilder sort(SortBuilder sort) {
if (sorts == null) {
sorts = Lists.newArrayList();
}
sortScripts.add(new ScriptSortTuple(script, type, params, order == Order.DESC));
return this;
}
/**
* Add a sort against the given field name and if it should be revered or not.
*
* @param name The name of the field to sort by
* @param reverse Should the sort be reversed or not
*/
public SearchSourceBuilder sort(String name, boolean reverse) {
if (sortFields == null) {
sortFields = newArrayListWithCapacity(2);
}
sortFields.add(new SortTuple(name, reverse));
sorts.add(sort);
return this;
}
@ -378,35 +341,14 @@ public class SearchSourceBuilder implements ToXContent {
builder.endObject();
}
if (sortFields != null || sortScripts != null) {
builder.field("sort");
builder.startObject();
if (sortFields != null) {
for (SortTuple sortTuple : sortFields) {
builder.field(sortTuple.fieldName());
builder.startObject();
if (sortTuple.reverse()) {
builder.field("reverse", true);
}
builder.endObject();
}
if (sorts != null) {
builder.startArray("sort");
for (SortBuilder sort : sorts) {
builder.startObject();
sort.toXContent(builder, params);
builder.endObject();
}
if (sortScripts != null) {
for (ScriptSortTuple scriptSort : sortScripts) {
builder.startObject("_script");
builder.field("script", scriptSort.script());
builder.field("type", scriptSort.type());
if (scriptSort.params() != null) {
builder.field("params");
builder.map(scriptSort.params());
}
if (scriptSort.reverse()) {
builder.field("reverse", true);
}
builder.endObject();
}
}
builder.endObject();
builder.endArray();
}
if (indexBoost != null) {
@ -457,52 +399,4 @@ public class SearchSourceBuilder implements ToXContent {
return params;
}
}
private static class SortTuple {
private final String fieldName;
private final boolean reverse;
private SortTuple(String fieldName, boolean reverse) {
this.fieldName = fieldName;
this.reverse = reverse;
}
public String fieldName() {
return fieldName;
}
public boolean reverse() {
return reverse;
}
}
private static class ScriptSortTuple {
private final String script;
private final String type;
private final Map<String, Object> params;
private final boolean reverse;
private ScriptSortTuple(String script, String type, Map<String, Object> params, boolean reverse) {
this.script = script;
this.type = type;
this.params = params;
this.reverse = reverse;
}
public String script() {
return script;
}
public String type() {
return type;
}
public Map<String, Object> params() {
return params;
}
public boolean reverse() {
return reverse;
}
}
}

View File

@ -140,7 +140,7 @@ public class GeoDistanceFacetBuilder extends AbstractFacetBuilder {
}
/**
* The geo distance type used to compute the distnace.
* The geo distance type used to compute the distance.
*/
public GeoDistanceFacetBuilder geoDistance(GeoDistance geoDistance) {
this.geoDistance = geoDistance;

View File

@ -23,12 +23,17 @@ import org.apache.lucene.search.FieldComparatorSource;
import org.apache.lucene.search.Sort;
import org.apache.lucene.search.SortField;
import org.elasticsearch.common.collect.Lists;
import org.elasticsearch.common.lucene.geo.GeoDistance;
import org.elasticsearch.common.lucene.geo.GeoDistanceDataComparator;
import org.elasticsearch.common.lucene.geo.GeoHashUtils;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.XContentParser;
import org.elasticsearch.index.field.function.FieldsFunction;
import org.elasticsearch.index.field.function.script.ScriptFieldsFunction;
import org.elasticsearch.index.field.function.sort.DoubleFieldsFunctionDataComparator;
import org.elasticsearch.index.field.function.sort.StringFieldsFunctionDataComparator;
import org.elasticsearch.index.mapper.FieldMapper;
import org.elasticsearch.index.mapper.xcontent.XContentGeoPointFieldMapper;
import org.elasticsearch.search.SearchParseElement;
import org.elasticsearch.search.SearchParseException;
import org.elasticsearch.search.internal.SearchContext;
@ -50,6 +55,7 @@ public class SortParseElement implements SearchParseElement {
public static final String SCRIPT_FIELD_NAME = "_script";
public static final String SCORE_FIELD_NAME = "_score";
public static final String DOC_FIELD_NAME = "_doc";
public static final String GEO_DISTANCE_FIELD_NAME = "_geo_distance";
public SortParseElement() {
}
@ -60,6 +66,7 @@ public class SortParseElement implements SearchParseElement {
if (token == XContentParser.Token.START_ARRAY) {
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
if (token == XContentParser.Token.START_OBJECT) {
//TODO move to pluggable parsers, similar to facets. Builders already exists...
addCompoundSortField(parser, context, sortFields);
} else if (token == XContentParser.Token.VALUE_STRING) {
addSortField(context, sortFields, parser.text(), false);
@ -80,9 +87,6 @@ public class SortParseElement implements SearchParseElement {
String fieldName = parser.currentName();
boolean reverse = false;
String innerJsonName = null;
String script = null;
String type = null;
Map<String, Object> params = null;
token = parser.nextToken();
if (token == XContentParser.Token.VALUE_STRING) {
String direction = parser.text();
@ -91,6 +95,11 @@ public class SortParseElement implements SearchParseElement {
} else if (direction.equals("desc")) {
reverse = !SCORE_FIELD_NAME.equals(fieldName);
}
addSortField(context, sortFields, fieldName, reverse);
} else if (GEO_DISTANCE_FIELD_NAME.equals(fieldName)) {
addGeoDistanceSortField(parser, context, sortFields);
} else if (SCRIPT_FIELD_NAME.equals(fieldName)) {
addScriptSortField(parser, context, sortFields);
} else {
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
@ -104,34 +113,9 @@ public class SortParseElement implements SearchParseElement {
} else if ("desc".equals(parser.text())) {
reverse = !SCORE_FIELD_NAME.equals(fieldName);
}
} else if ("script".equals(innerJsonName)) {
script = parser.text();
} else if ("type".equals(innerJsonName)) {
type = parser.text();
} else if ("params".equals(innerJsonName)) {
params = parser.map();
}
}
}
}
if (SCRIPT_FIELD_NAME.equals(fieldName)) {
if (script == null) {
throw new SearchParseException(context, "_script sorting requires setting the script to sort by");
}
if (type == null) {
throw new SearchParseException(context, "_script sorting requires setting the type of the script");
}
FieldsFunction fieldsFunction = new ScriptFieldsFunction(script, context.scriptService(), context.mapperService(), context.fieldDataCache());
FieldComparatorSource fieldComparatorSource;
if ("string".equals(type)) {
fieldComparatorSource = StringFieldsFunctionDataComparator.comparatorSource(fieldsFunction, params);
} else if ("number".equals(type)) {
fieldComparatorSource = DoubleFieldsFunctionDataComparator.comparatorSource(fieldsFunction, params);
} else {
throw new SearchParseException(context, "custom script sort type [" + type + "] not supported");
}
sortFields.add(new SortField(fieldName, fieldComparatorSource, reverse));
} else {
addSortField(context, sortFields, fieldName, reverse);
}
}
@ -159,4 +143,137 @@ public class SortParseElement implements SearchParseElement {
sortFields.add(new SortField(fieldName, fieldMapper.fieldDataType().newFieldComparatorSource(context.fieldDataCache()), reverse));
}
}
/**
* <pre>
* "_script" : {
* "script" : "doc[...]",
* "order" : "asc"
* }
* </pre>
*/
private void addScriptSortField(XContentParser parser, SearchContext context, List<SortField> sortFields) throws IOException {
String script = null;
String type = null;
Map<String, Object> params = null;
boolean reverse = false;
XContentParser.Token token;
String currentName = parser.currentName();
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentName = parser.currentName();
} else if (token.isValue()) {
if ("reverse".equals(currentName)) {
reverse = parser.booleanValue();
} else if ("order".equals(currentName)) {
reverse = "desc".equals(parser.text());
} else if ("script".equals(currentName)) {
script = parser.text();
} else if ("type".equals(currentName)) {
type = parser.text();
} else if ("params".equals(currentName)) {
params = parser.map();
}
}
}
if (script == null) {
throw new SearchParseException(context, "_script sorting requires setting the script to sort by");
}
if (type == null) {
throw new SearchParseException(context, "_script sorting requires setting the type of the script");
}
FieldsFunction fieldsFunction = new ScriptFieldsFunction(script, context.scriptService(), context.mapperService(), context.fieldDataCache());
FieldComparatorSource fieldComparatorSource;
if ("string".equals(type)) {
fieldComparatorSource = StringFieldsFunctionDataComparator.comparatorSource(fieldsFunction, params);
} else if ("number".equals(type)) {
fieldComparatorSource = DoubleFieldsFunctionDataComparator.comparatorSource(fieldsFunction, params);
} else {
throw new SearchParseException(context, "custom script sort type [" + type + "] not supported");
}
sortFields.add(new SortField("_script", fieldComparatorSource, reverse));
}
/**
* <pre>
* "_geo_distance" : {
* "pin.location" : {
*
* },
* "order" : "asc"
* }
* </pre>
*/
private void addGeoDistanceSortField(XContentParser parser, SearchContext context, List<SortField> sortFields) throws IOException {
String fieldName = null;
double lat = Double.NaN;
double lon = Double.NaN;
DistanceUnit unit = DistanceUnit.KILOMETERS;
GeoDistance geoDistance = GeoDistance.ARC;
boolean reverse = false;
XContentParser.Token token;
String currentName = parser.currentName();
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentName = parser.currentName();
} else if (token == XContentParser.Token.START_ARRAY) {
token = parser.nextToken();
lat = parser.doubleValue();
token = parser.nextToken();
lon = parser.doubleValue();
while ((token = parser.nextToken()) != XContentParser.Token.END_ARRAY) {
}
fieldName = currentName;
} else if (token == XContentParser.Token.START_OBJECT) {
// the json in the format of -> field : { lat : 30, lon : 12 }
fieldName = currentName;
while ((token = parser.nextToken()) != XContentParser.Token.END_OBJECT) {
if (token == XContentParser.Token.FIELD_NAME) {
currentName = parser.currentName();
} else if (token.isValue()) {
if (currentName.equals(XContentGeoPointFieldMapper.Names.LAT)) {
lat = parser.doubleValue();
} else if (currentName.equals(XContentGeoPointFieldMapper.Names.LON)) {
lon = parser.doubleValue();
} else if (currentName.equals(XContentGeoPointFieldMapper.Names.GEOHASH)) {
double[] values = GeoHashUtils.decode(parser.text());
lat = values[0];
lon = values[1];
}
}
}
} else if (token.isValue()) {
if ("reverse".equals(currentName)) {
reverse = parser.booleanValue();
} else if ("order".equals(currentName)) {
reverse = "desc".equals(parser.text());
} else if (currentName.equals("unit")) {
unit = DistanceUnit.fromString(parser.text());
} else if (currentName.equals("distance_type") || currentName.equals("distanceType")) {
geoDistance = GeoDistance.fromString(parser.text());
} else {
// assume the value is the actual value
String value = parser.text();
int comma = value.indexOf(',');
if (comma != -1) {
lat = Double.parseDouble(value.substring(0, comma).trim());
lon = Double.parseDouble(value.substring(comma + 1).trim());
} else {
double[] values = GeoHashUtils.decode(value);
lat = values[0];
lon = values[1];
}
fieldName = currentName;
}
}
}
sortFields.add(new SortField(fieldName, GeoDistanceDataComparator.comparatorSource(fieldName, lat, lon, unit, geoDistance, context.fieldDataCache(), context.mapperService()), reverse));
}
}

View File

@ -0,0 +1,51 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.search.sort;
import org.elasticsearch.common.xcontent.builder.XContentBuilder;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class FieldSortBuilder extends SortBuilder {
private final String fieldName;
private SortOrder order;
public FieldSortBuilder(String fieldName) {
this.fieldName = fieldName;
}
public FieldSortBuilder order(SortOrder order) {
this.order = order;
return this;
}
@Override public void toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject(fieldName);
if (order == SortOrder.DESC) {
builder.field("reverse", true);
}
builder.endObject();
}
}

View File

@ -0,0 +1,109 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.search.sort;
import org.elasticsearch.common.lucene.geo.GeoDistance;
import org.elasticsearch.common.unit.DistanceUnit;
import org.elasticsearch.common.xcontent.builder.XContentBuilder;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class GeoDistanceSortBuilder extends SortBuilder {
final String fieldName;
private double lat;
private double lon;
private String geohash;
private GeoDistance geoDistance;
private DistanceUnit unit;
private SortOrder order;
public GeoDistanceSortBuilder(String fieldName) {
this.fieldName = fieldName;
}
/**
* The point to create the range distance facets from.
*
* @param lat latitude.
* @param lon longitude.
*/
public GeoDistanceSortBuilder point(double lat, double lon) {
this.lat = lat;
this.lon = lon;
return this;
}
/**
* The geohash of the geo point to create the range distance facets from.
*/
public GeoDistanceSortBuilder geohash(String geohash) {
this.geohash = geohash;
return this;
}
/**
* The geo distance type used to compute the distance.
*/
public GeoDistanceSortBuilder geoDistance(GeoDistance geoDistance) {
this.geoDistance = geoDistance;
return this;
}
/**
* The distance unit to use. Defaults to {@link org.elasticsearch.common.unit.DistanceUnit#KILOMETERS}
*/
public GeoDistanceSortBuilder unit(DistanceUnit unit) {
this.unit = unit;
return this;
}
public GeoDistanceSortBuilder order(SortOrder order) {
this.order = order;
return this;
}
@Override public void toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject("_geo_distance");
if (geohash != null) {
builder.field(fieldName, geohash);
} else {
builder.startArray(fieldName).value(lat).value(lon).endArray();
}
if (unit != null) {
builder.field("unit", unit);
}
if (geoDistance != null) {
builder.field("distance_type", geoDistance.name().toLowerCase());
}
if (order == SortOrder.DESC) {
builder.field("reverse", true);
}
builder.endObject();
}
}

View File

@ -0,0 +1,45 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.search.sort;
import org.elasticsearch.common.xcontent.builder.XContentBuilder;
import java.io.IOException;
/**
* @author kimchy (shay.banon)
*/
public class ScoreSortBuilder extends SortBuilder {
private SortOrder order;
public ScoreSortBuilder order(SortOrder order) {
this.order = order;
return this;
}
@Override public void toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject("_score");
if (order == SortOrder.ASC) {
builder.field("reverse", true);
}
builder.endObject();
}
}

View File

@ -0,0 +1,72 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.search.sort;
import org.elasticsearch.common.collect.Maps;
import org.elasticsearch.common.xcontent.builder.XContentBuilder;
import java.io.IOException;
import java.util.Map;
/**
* @author kimchy (shay.banon)
*/
public class ScriptSortBuilder extends SortBuilder {
private final String script;
private final String type;
private SortOrder order;
private Map<String, Object> params;
public ScriptSortBuilder(String script, String type) {
this.script = script;
this.type = type;
}
public ScriptSortBuilder param(String name, Object value) {
if (params == null) {
params = Maps.newHashMap();
}
params.put(name, value);
return this;
}
public ScriptSortBuilder order(SortOrder order) {
this.order = order;
return this;
}
@Override public void toXContent(XContentBuilder builder, Params params) throws IOException {
builder.startObject("_script");
builder.field("script", script);
builder.field("type", type);
if (order == SortOrder.DESC) {
builder.field("reverse", true);
}
if (this.params != null) {
builder.field("params");
builder.map(this.params);
}
builder.endObject();
}
}

View File

@ -0,0 +1,30 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.search.sort;
import org.elasticsearch.common.xcontent.ToXContent;
/**
* @author kimchy (shay.banon)
*/
public abstract class SortBuilder implements ToXContent {
public abstract SortBuilder order(SortOrder order);
}

View File

@ -0,0 +1,42 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.search.sort;
/**
* @author kimchy (shay.banon)
*/
public class SortBuilders {
public static ScoreSortBuilder scoreSort() {
return new ScoreSortBuilder();
}
public static FieldSortBuilder fieldSort(String field) {
return new FieldSortBuilder(field);
}
public static ScriptSortBuilder scriptSort(String script, String type) {
return new ScriptSortBuilder(script, type);
}
public static GeoDistanceSortBuilder geoDistanceSort(String fieldName) {
return new GeoDistanceSortBuilder(fieldName);
}
}

View File

@ -0,0 +1,28 @@
/*
* Licensed to Elastic Search and Shay Banon under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. Elastic Search 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.search.sort;
/**
* @author kimchy (shay.banon)
*/
public enum SortOrder {
ASC,
DESC
}

View File

@ -32,6 +32,7 @@ import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.facets.FacetBuilders;
import org.elasticsearch.search.facets.query.QueryFacet;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@ -110,7 +111,7 @@ public class TransportTwoServersSearchTests extends AbstractNodesTests {
@Test public void testDfsQueryThenFetchWithSort() throws Exception {
SearchSourceBuilder source = searchSource()
.query(termQuery("multi", "test"))
.from(0).size(60).explain(true).sort("age", false);
.from(0).size(60).explain(true).sort("age", SortOrder.ASC);
SearchResponse searchResponse = client.search(searchRequest("test").source(source).searchType(DFS_QUERY_THEN_FETCH).scroll(new Scroll(timeValueMinutes(10)))).actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.shardFailures()), searchResponse.shardFailures().length, equalTo(0));
@ -162,7 +163,7 @@ public class TransportTwoServersSearchTests extends AbstractNodesTests {
@Test public void testQueryThenFetchWithSort() throws Exception {
SearchSourceBuilder source = searchSource()
.query(termQuery("multi", "test"))
.from(0).size(60).explain(true).sort("age", false);
.from(0).size(60).explain(true).sort("age", SortOrder.ASC);
SearchResponse searchResponse = client.search(searchRequest("test").source(source).searchType(QUERY_THEN_FETCH).scroll(new Scroll(timeValueMinutes(10)))).actionGet();
assertThat("Failures " + Arrays.toString(searchResponse.shardFailures()), searchResponse.shardFailures().length, equalTo(0));

View File

@ -47,6 +47,7 @@ import org.elasticsearch.search.internal.InternalSearchResponse;
import org.elasticsearch.search.query.QuerySearchRequest;
import org.elasticsearch.search.query.QuerySearchResult;
import org.elasticsearch.search.query.QuerySearchResultProvider;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@ -178,7 +179,7 @@ public class TwoInstanceEmbeddedSearchTests extends AbstractNodesTests {
@Test public void testDfsQueryThenFetchWithSort() throws Exception {
SearchSourceBuilder sourceBuilder = searchSource()
.query(termQuery("multi", "test"))
.from(0).size(60).explain(true).sort("age", false);
.from(0).size(60).explain(true).sort("age", SortOrder.ASC);
List<DfsSearchResult> dfsResults = newArrayList();
for (ShardsIterator shardsIt : indicesService.searchShards(clusterService.state(), new String[]{"test"}, null)) {
@ -320,7 +321,7 @@ public class TwoInstanceEmbeddedSearchTests extends AbstractNodesTests {
@Test public void testSimpleFacets() {
SearchSourceBuilder sourceBuilder = searchSource()
.query(termQuery("multi", "test"))
.from(0).size(20).explain(true).sort("age", false)
.from(0).size(20).explain(true).sort("age", SortOrder.ASC)
.facet(FacetBuilders.queryFacet("all", termQuery("multi", "test")))
.facet(FacetBuilders.queryFacet("test1", termQuery("name", "test1")));

View File

@ -52,6 +52,7 @@ import org.elasticsearch.search.internal.InternalSearchResponse;
import org.elasticsearch.search.query.QuerySearchRequest;
import org.elasticsearch.search.query.QuerySearchResult;
import org.elasticsearch.search.query.QuerySearchResultProvider;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@ -183,7 +184,7 @@ public class TwoInstanceUnbalancedShardsEmbeddedSearchTests extends AbstractNode
@Test public void testDfsQueryFetchWithSort() throws Exception {
SearchSourceBuilder sourceBuilder = searchSource()
.query(termQuery("multi", "test"))
.from(0).size(60).explain(true).sort("age", false);
.from(0).size(60).explain(true).sort("age", SortOrder.ASC);
List<DfsSearchResult> dfsResults = newArrayList();
for (ShardsIterator shardsIt : indicesService.searchShards(clusterService.state(), new String[]{"test"}, null)) {
@ -326,7 +327,7 @@ public class TwoInstanceUnbalancedShardsEmbeddedSearchTests extends AbstractNode
@Test public void testSimpleFacets() {
SearchSourceBuilder sourceBuilder = searchSource()
.query(termQuery("multi", "test"))
.from(0).size(20).explain(true).sort("age", false)
.from(0).size(20).explain(true).sort("age", SortOrder.ASC)
.facet(queryFacet("all").query(termQuery("multi", "test")))
.facet(queryFacet("test1").query(termQuery("name", "test1")));

View File

@ -22,6 +22,8 @@ package org.elasticsearch.test.integration.search.geo;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@ -133,5 +135,35 @@ public class GeoDistanceTests extends AbstractNodesTests {
for (SearchHit hit : searchResponse.hits()) {
assertThat(hit.id(), anyOf(equalTo("1"), equalTo("3"), equalTo("4"), equalTo("5")));
}
// SORTING
searchResponse = client.prepareSearch().setQuery(matchAllQuery())
.addSort(SortBuilders.geoDistanceSort("location").point(40.7143528, -74.0059731).order(SortOrder.ASC))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(7l));
assertThat(searchResponse.hits().hits().length, equalTo(7));
assertThat(searchResponse.hits().getAt(0).id(), equalTo("1"));
assertThat(searchResponse.hits().getAt(1).id(), equalTo("3"));
assertThat(searchResponse.hits().getAt(2).id(), equalTo("4"));
assertThat(searchResponse.hits().getAt(3).id(), equalTo("5"));
assertThat(searchResponse.hits().getAt(4).id(), equalTo("6"));
assertThat(searchResponse.hits().getAt(5).id(), equalTo("2"));
assertThat(searchResponse.hits().getAt(6).id(), equalTo("7"));
searchResponse = client.prepareSearch().setQuery(matchAllQuery())
.addSort(SortBuilders.geoDistanceSort("location").point(40.7143528, -74.0059731).order(SortOrder.DESC))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(7l));
assertThat(searchResponse.hits().hits().length, equalTo(7));
assertThat(searchResponse.hits().getAt(6).id(), equalTo("1"));
assertThat(searchResponse.hits().getAt(5).id(), equalTo("3"));
assertThat(searchResponse.hits().getAt(4).id(), equalTo("4"));
assertThat(searchResponse.hits().getAt(3).id(), equalTo("5"));
assertThat(searchResponse.hits().getAt(2).id(), equalTo("6"));
assertThat(searchResponse.hits().getAt(1).id(), equalTo("2"));
assertThat(searchResponse.hits().getAt(0).id(), equalTo("7"));
}
}

View File

@ -22,6 +22,7 @@ package org.elasticsearch.test.integration.search.scriptfield;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.common.collect.MapBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@ -32,7 +33,6 @@ import java.util.Map;
import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.elasticsearch.index.query.xcontent.QueryBuilders.*;
import static org.elasticsearch.search.builder.SearchSourceBuilder.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
@ -77,7 +77,7 @@ public class ScriptFieldSearchTests extends AbstractNodesTests {
logger.info("running doc['num1'].value");
SearchResponse response = client.prepareSearch()
.setQuery(matchAllQuery())
.addSort("num1", Order.ASC)
.addSort("num1", SortOrder.ASC)
.addScriptField("sNum1", "doc['num1'].value")
.addScriptField("date1", "doc['date'].date.millis")
.execute().actionGet();
@ -98,7 +98,7 @@ public class ScriptFieldSearchTests extends AbstractNodesTests {
Map<String, Object> params = MapBuilder.<String, Object>newMapBuilder().put("factor", 2.0).map();
response = client.prepareSearch()
.setQuery(matchAllQuery())
.addSort("num1", Order.ASC)
.addSort("num1", SortOrder.ASC)
.addScriptField("sNum1", "doc['num1'].value * factor", params)
.execute().actionGet();

View File

@ -21,6 +21,7 @@ package org.elasticsearch.test.integration.search.scriptfilter;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Client;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterMethod;
import org.testng.annotations.BeforeMethod;
@ -30,7 +31,6 @@ import static org.elasticsearch.client.Requests.*;
import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.elasticsearch.index.query.xcontent.FilterBuilders.*;
import static org.elasticsearch.index.query.xcontent.QueryBuilders.*;
import static org.elasticsearch.search.builder.SearchSourceBuilder.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
@ -75,7 +75,7 @@ public class ScriptFilterSearchTests extends AbstractNodesTests {
logger.info("running doc['num1'].value > 1");
SearchResponse response = client.prepareSearch()
.setQuery(filtered(matchAllQuery(), scriptFilter("doc['num1'].value > 1")))
.addSort("num1", Order.ASC)
.addSort("num1", SortOrder.ASC)
.addScriptField("sNum1", "doc['num1'].value")
.execute().actionGet();
@ -88,7 +88,7 @@ public class ScriptFilterSearchTests extends AbstractNodesTests {
logger.info("running doc['num1'].value > param1");
response = client.prepareSearch()
.setQuery(filtered(matchAllQuery(), scriptFilter("doc['num1'].value > param1").addParam("param1", 2)))
.addSort("num1", Order.ASC)
.addSort("num1", SortOrder.ASC)
.addScriptField("sNum1", "doc['num1'].value")
.execute().actionGet();
@ -99,7 +99,7 @@ public class ScriptFilterSearchTests extends AbstractNodesTests {
logger.info("running doc['num1'].value > param1");
response = client.prepareSearch()
.setQuery(filtered(matchAllQuery(), scriptFilter("doc['num1'].value > param1").addParam("param1", -1)))
.addSort("num1", Order.ASC)
.addSort("num1", SortOrder.ASC)
.addScriptField("sNum1", "doc['num1'].value")
.execute().actionGet();

View File

@ -22,7 +22,7 @@ package org.elasticsearch.test.integration.search.sort;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.action.search.ShardSearchFailure;
import org.elasticsearch.client.Client;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.sort.SortOrder;
import org.elasticsearch.test.integration.AbstractNodesTests;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
@ -30,6 +30,7 @@ import org.testng.annotations.Test;
import static org.elasticsearch.common.xcontent.XContentFactory.*;
import static org.elasticsearch.index.query.xcontent.QueryBuilders.*;
import static org.elasticsearch.search.sort.SortBuilders.*;
import static org.hamcrest.MatcherAssert.*;
import static org.hamcrest.Matchers.*;
@ -83,7 +84,7 @@ public class SimpleSortTests extends AbstractNodesTests {
SearchResponse searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSort("svalue", SearchSourceBuilder.Order.ASC)
.addSort("svalue", SortOrder.ASC)
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -95,7 +96,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSortScript("doc['svalue'].value", "string", SearchSourceBuilder.Order.ASC)
.addSort(scriptSort("doc['svalue'].value", "string").order(SortOrder.ASC))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -105,7 +106,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSort("svalue", SearchSourceBuilder.Order.DESC)
.addSort("svalue", SortOrder.DESC)
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -115,7 +116,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSortScript("doc['svalue'].value", "string", SearchSourceBuilder.Order.DESC)
.addSort(scriptSort("doc['svalue'].value", "string").order(SortOrder.DESC))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -125,7 +126,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSort("ivalue", SearchSourceBuilder.Order.ASC)
.addSort("ivalue", SortOrder.ASC)
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -137,7 +138,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSortScript("doc['ivalue'].value", "number", SearchSourceBuilder.Order.ASC)
.addSort(scriptSort("doc['ivalue'].value", "number").order(SortOrder.ASC))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -147,7 +148,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSort("ivalue", SearchSourceBuilder.Order.DESC)
.addSort("ivalue", SortOrder.DESC)
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -159,7 +160,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSortScript("doc['ivalue'].value", "number", SearchSourceBuilder.Order.DESC)
.addSort(scriptSort("doc['ivalue'].value", "string").order(SortOrder.DESC))
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -169,7 +170,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSort("dvalue", SearchSourceBuilder.Order.ASC)
.addSort("dvalue", SortOrder.ASC)
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -179,7 +180,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSort("dvalue", SearchSourceBuilder.Order.DESC)
.addSort("dvalue", SortOrder.DESC)
.execute().actionGet();
assertThat(searchResponse.hits().getTotalHits(), equalTo(2l));
@ -217,7 +218,7 @@ public class SimpleSortTests extends AbstractNodesTests {
SearchResponse searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSort("svalue", SearchSourceBuilder.Order.ASC)
.addSort("svalue", SortOrder.ASC)
.execute().actionGet();
if (searchResponse.failedShards() > 0) {
@ -236,7 +237,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(matchAllQuery())
.addScriptField("id", "doc['id'].value")
.addSort("svalue", SearchSourceBuilder.Order.DESC)
.addSort("svalue", SortOrder.DESC)
.execute().actionGet();
if (searchResponse.failedShards() > 0) {
@ -256,7 +257,7 @@ public class SimpleSortTests extends AbstractNodesTests {
searchResponse = client.prepareSearch()
.setQuery(termQuery("id", "2"))
.addScriptField("id", "doc['id'].value")
.addSort("svalue", SearchSourceBuilder.Order.DESC)
.addSort("svalue", SortOrder.DESC)
.execute().actionGet();
if (searchResponse.failedShards() > 0) {