Skip to content

Commit 031daf6

Browse files
committed
Fix search_after with geo distance sorting (#26891)
Support for search_after and geo distance sorting is broken when the optimized LatLonDocValuesField.distanceSort is used. This commit fixes the parsing of the search_after value for this case.
1 parent 9a4e582 commit 031daf6

File tree

2 files changed

+47
-11
lines changed

2 files changed

+47
-11
lines changed

core/src/main/java/org/elasticsearch/search/searchafter/SearchAfterBuilder.java

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,6 @@
3030
import org.elasticsearch.common.io.stream.StreamOutput;
3131
import org.elasticsearch.common.io.stream.Writeable;
3232
import org.elasticsearch.common.text.Text;
33-
import org.elasticsearch.common.xcontent.ToXContent.Params;
3433
import org.elasticsearch.common.xcontent.ToXContentObject;
3534
import org.elasticsearch.common.xcontent.XContentBuilder;
3635
import org.elasticsearch.common.xcontent.XContentFactory;
@@ -131,21 +130,25 @@ public static FieldDoc buildFieldDoc(SortAndFormats sort, Object[] values) {
131130
return new FieldDoc(Integer.MAX_VALUE, 0, fieldValues);
132131
}
133132

134-
private static SortField.Type extractSortType(SortField sortField) {
135-
if (sortField instanceof SortedSetSortField) {
133+
/**
134+
* Returns the inner {@link SortField.Type} expected for this sort field.
135+
*/
136+
static SortField.Type extractSortType(SortField sortField) {
137+
if (sortField.getComparatorSource() instanceof IndexFieldData.XFieldComparatorSource) {
138+
return ((IndexFieldData.XFieldComparatorSource) sortField.getComparatorSource()).reducedType();
139+
} else if (sortField instanceof SortedSetSortField) {
136140
return SortField.Type.STRING;
137141
} else if (sortField instanceof SortedNumericSortField) {
138142
return ((SortedNumericSortField) sortField).getNumericType();
143+
} else if ("LatLonPointSortField".equals(sortField.getClass().getSimpleName())) {
144+
// for geo distance sorting
145+
return SortField.Type.DOUBLE;
139146
} else {
140147
return sortField.getType();
141148
}
142149
}
143150

144-
private static Object convertValueFromSortField(Object value, SortField sortField, DocValueFormat format) {
145-
if (sortField.getComparatorSource() instanceof IndexFieldData.XFieldComparatorSource) {
146-
IndexFieldData.XFieldComparatorSource cmpSource = (IndexFieldData.XFieldComparatorSource) sortField.getComparatorSource();
147-
return convertValueFromSortType(sortField.getField(), cmpSource.reducedType(), value, format);
148-
}
151+
static Object convertValueFromSortField(Object value, SortField sortField, DocValueFormat format) {
149152
SortField.Type sortType = extractSortType(sortField);
150153
return convertValueFromSortType(sortField.getField(), sortType, value, format);
151154
}

core/src/test/java/org/elasticsearch/search/searchafter/SearchAfterBuilderTests.java

Lines changed: 36 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,11 @@
1919

2020
package org.elasticsearch.search.searchafter;
2121

22+
import org.apache.lucene.document.LatLonDocValuesField;
23+
import org.apache.lucene.search.FieldComparator;
24+
import org.apache.lucene.search.SortField;
25+
import org.apache.lucene.search.SortedNumericSortField;
26+
import org.apache.lucene.search.SortedSetSortField;
2227
import org.elasticsearch.common.geo.GeoPoint;
2328
import org.elasticsearch.common.io.stream.NamedWriteableRegistry;
2429
import org.elasticsearch.common.text.Text;
@@ -27,13 +32,16 @@
2732
import org.elasticsearch.common.xcontent.XContentParser;
2833
import org.elasticsearch.common.xcontent.XContentType;
2934
import org.elasticsearch.common.xcontent.json.JsonXContent;
35+
import org.elasticsearch.index.fielddata.IndexFieldData;
36+
import org.elasticsearch.search.MultiValueMode;
3037
import org.elasticsearch.test.ESTestCase;
31-
import org.hamcrest.Matchers;
3238

3339
import java.io.IOException;
3440
import java.util.Collections;
3541

42+
import static org.elasticsearch.search.searchafter.SearchAfterBuilder.extractSortType;
3643
import static org.elasticsearch.test.EqualsHashCodeTestUtils.checkEqualsAndHashCode;
44+
import static org.hamcrest.Matchers.equalTo;
3745

3846
public class SearchAfterBuilderTests extends ESTestCase {
3947
private static final int NUMBER_OF_TESTBUILDERS = 20;
@@ -182,7 +190,7 @@ public void testWithNullArray() throws Exception {
182190
builder.setSortValues(null);
183191
fail("Should fail on null array.");
184192
} catch (NullPointerException e) {
185-
assertThat(e.getMessage(), Matchers.equalTo("Values cannot be null."));
193+
assertThat(e.getMessage(), equalTo("Values cannot be null."));
186194
}
187195
}
188196

@@ -192,7 +200,7 @@ public void testWithEmptyArray() throws Exception {
192200
builder.setSortValues(new Object[0]);
193201
fail("Should fail on empty array.");
194202
} catch (IllegalArgumentException e) {
195-
assertThat(e.getMessage(), Matchers.equalTo("Values must contains at least one value."));
203+
assertThat(e.getMessage(), equalTo("Values must contains at least one value."));
196204
}
197205
}
198206

@@ -215,4 +223,29 @@ private static void randomSearchFromBuilderWithSortValueThrows(Object containing
215223
Exception e = expectThrows(IllegalArgumentException.class, () -> builder.setSortValues(values));
216224
assertEquals(e.getMessage(), "Can't handle search_after field value of type [" + containing.getClass() + "]");
217225
}
226+
227+
public void testExtractSortType() throws Exception {
228+
SortField.Type type = extractSortType(LatLonDocValuesField.newDistanceSort("field", 0.0, 180.0));
229+
assertThat(type, equalTo(SortField.Type.DOUBLE));
230+
IndexFieldData.XFieldComparatorSource source = new IndexFieldData.XFieldComparatorSource(null, MultiValueMode.MIN, null) {
231+
@Override
232+
public SortField.Type reducedType() {
233+
return SortField.Type.STRING;
234+
}
235+
236+
@Override
237+
public FieldComparator<?> newComparator(String fieldname, int numHits, int sortPos, boolean reversed) {
238+
return null;
239+
}
240+
};
241+
242+
type = extractSortType(new SortField("field", source));
243+
assertThat(type, equalTo(SortField.Type.STRING));
244+
245+
type = extractSortType(new SortedNumericSortField("field", SortField.Type.DOUBLE));
246+
assertThat(type, equalTo(SortField.Type.DOUBLE));
247+
248+
type = extractSortType(new SortedSetSortField("field", false));
249+
assertThat(type, equalTo(SortField.Type.STRING));
250+
}
218251
}

0 commit comments

Comments
 (0)