Skip to content

Commit

Permalink
Allow mismatched sort-by field types if there are no docs to sort (el…
Browse files Browse the repository at this point in the history
…astic#102779)

When searching multiple indices and a field only exists in ONE of the
indices, we should allow sorting by that field, regardless of the
"unmapped" type provided.

closes: elastic#102723
  • Loading branch information
benwtrent authored Nov 30, 2023
1 parent 02c5295 commit 43dc74b
Show file tree
Hide file tree
Showing 3 changed files with 36 additions and 9 deletions.
5 changes: 5 additions & 0 deletions docs/changelog/102779.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
pr: 102779
summary: Allow mismatched sort-by field types if there are no docs to sort
area: Search
type: bug
issues: []
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ public void testIssue8226() {
);
}

public void testIssue6614() throws ExecutionException, InterruptedException {
public void testIssue6614() throws InterruptedException {
List<IndexRequestBuilder> builders = new ArrayList<>();
boolean strictTimeBasedIndices = randomBoolean();
final int numIndices = randomIntBetween(2, 25); // at most 25 days in the month
Expand Down Expand Up @@ -2137,4 +2137,19 @@ public void testSortMixedFieldTypes() {
}
}

public void testSortMixedFieldTypesWithNoDocsForOneType() {
assertAcked(prepareCreate("index_long").setMapping("foo", "type=long").get());
assertAcked(prepareCreate("index_other").setMapping("bar", "type=keyword").get());
assertAcked(prepareCreate("index_double").setMapping("foo", "type=double").get());

prepareIndex("index_long").setId("1").setSource("foo", "123").get();
prepareIndex("index_long").setId("2").setSource("foo", "124").get();
prepareIndex("index_other").setId("1").setSource("bar", "124").get();
refresh();

assertNoFailures(
prepareSearch("index_long", "index_double", "index_other").addSort(new FieldSortBuilder("foo").unmappedType("boolean"))
.setSize(10)
);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -241,8 +241,7 @@ static TopDocs mergeTopDocs(Collection<TopDocs> results, int topN, int from) {
final TopFieldGroups[] shardTopDocs = results.toArray(new TopFieldGroups[numShards]);
mergedTopDocs = TopFieldGroups.merge(sort, from, topN, shardTopDocs, false);
} else if (topDocs instanceof TopFieldDocs firstTopDocs) {
checkSameSortTypes(results, firstTopDocs.fields);
final Sort sort = new Sort(firstTopDocs.fields);
final Sort sort = checkSameSortTypes(results, firstTopDocs.fields);
final TopFieldDocs[] shardTopDocs = results.toArray(new TopFieldDocs[numShards]);
mergedTopDocs = TopDocs.merge(sort, from, topN, shardTopDocs);
} else {
Expand All @@ -252,19 +251,26 @@ static TopDocs mergeTopDocs(Collection<TopDocs> results, int topN, int from) {
return mergedTopDocs;
}

private static void checkSameSortTypes(Collection<TopDocs> results, SortField[] firstSortFields) {
if (results.size() < 2) return;
private static Sort checkSameSortTypes(Collection<TopDocs> results, SortField[] firstSortFields) {
Sort sort = new Sort(firstSortFields);
if (results.size() < 2) return sort;

SortField.Type[] firstTypes = new SortField.Type[firstSortFields.length];
SortField.Type[] firstTypes = null;
boolean isFirstResult = true;
for (TopDocs topDocs : results) {
// We don't actually merge in empty score docs, so ignore potentially mismatched types if there are no docs
if (topDocs.scoreDocs == null || topDocs.scoreDocs.length == 0) {
continue;
}
SortField[] curSortFields = ((TopFieldDocs) topDocs).fields;
if (isFirstResult) {
sort = new Sort(curSortFields);
firstTypes = new SortField.Type[curSortFields.length];
for (int i = 0; i < curSortFields.length; i++) {
firstTypes[i] = getType(firstSortFields[i]);
firstTypes[i] = getType(curSortFields[i]);
if (firstTypes[i] == SortField.Type.CUSTOM) {
// for custom types that we can't resolve, we can't do the check
return;
return sort;
}
}
isFirstResult = false;
Expand All @@ -274,7 +280,7 @@ private static void checkSameSortTypes(Collection<TopDocs> results, SortField[]
if (curType != firstTypes[i]) {
if (curType == SortField.Type.CUSTOM) {
// for custom types that we can't resolve, we can't do the check
return;
return sort;
}
throw new IllegalArgumentException(
"Can't sort on field ["
Expand All @@ -289,6 +295,7 @@ private static void checkSameSortTypes(Collection<TopDocs> results, SortField[]
}
}
}
return sort;
}

private static SortField.Type getType(SortField sortField) {
Expand Down

0 comments on commit 43dc74b

Please sign in to comment.