Skip to content

Commit 81e8827

Browse files
committed
Fix automatic tracking of collapse with docvalue_fields (elastic#110103)
There were some optimizations that broke collapse fields automatically being added to `docvalue_fields` during the fetch phase. Consequently, users will get really weird errors like `unsupported_operation_exception`. This commit corrects the intended behavior of automatically including the collapse field in the docvalue_fields context during fetch if it isn't already included. closes: elastic#96510
1 parent 1d4a9f0 commit 81e8827

File tree

4 files changed

+32
-4
lines changed

4 files changed

+32
-4
lines changed

docs/changelog/110103.yaml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
pr: 110103
2+
summary: Fix automatic tracking of collapse with `docvalue_fields`
3+
area: Search
4+
type: bug
5+
issues: []

server/src/internalClusterTest/java/org/elasticsearch/search/CollapseSearchResultsIT.java

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,26 @@ public void testCollapse() {
3939
}
4040
);
4141
}
42+
43+
public void testCollapseWithDocValueFields() {
44+
final String indexName = "test_collapse";
45+
createIndex(indexName);
46+
final String collapseField = "collapse_field";
47+
final String otherField = "other_field";
48+
assertAcked(indicesAdmin().preparePutMapping(indexName).setSource(collapseField, "type=keyword", otherField, "type=keyword"));
49+
index(indexName, "id_1_0", Map.of(collapseField, "value1", otherField, "other_value1"));
50+
index(indexName, "id_1_1", Map.of(collapseField, "value1", otherField, "other_value2"));
51+
index(indexName, "id_2_0", Map.of(collapseField, "value2", otherField, "other_value3"));
52+
refresh(indexName);
53+
54+
assertNoFailuresAndResponse(
55+
prepareSearch(indexName).setQuery(new MatchAllQueryBuilder())
56+
.addDocValueField(otherField)
57+
.setCollapse(new CollapseBuilder(collapseField).setInnerHits(new InnerHitBuilder("ih").setSize(2))),
58+
searchResponse -> {
59+
assertEquals(collapseField, searchResponse.getHits().getCollapseField());
60+
assertEquals(Set.of(new BytesRef("value1"), new BytesRef("value2")), Set.of(searchResponse.getHits().getCollapseValues()));
61+
}
62+
);
63+
}
4264
}

server/src/main/java/org/elasticsearch/search/fetch/FetchContext.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ public FetchDocValuesContext docValuesContext() {
175175
searchContext.getSearchExecutionContext(),
176176
Collections.singletonList(new FieldAndFormat(name, null))
177177
);
178-
} else if (searchContext.docValuesContext().fields().stream().map(ff -> ff.field).anyMatch(name::equals) == false) {
178+
} else if (searchContext.docValuesContext().fields().stream().map(ff -> ff.field).noneMatch(name::equals)) {
179179
dvContext.fields().add(new FieldAndFormat(name, null));
180180
}
181181
}

server/src/main/java/org/elasticsearch/search/fetch/subphase/FetchDocValuesContext.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import org.elasticsearch.index.IndexSettings;
1111
import org.elasticsearch.index.query.SearchExecutionContext;
1212

13+
import java.util.ArrayList;
1314
import java.util.Collection;
1415
import java.util.LinkedHashMap;
1516
import java.util.List;
@@ -24,7 +25,7 @@
2425
*/
2526
public class FetchDocValuesContext {
2627

27-
private final Collection<FieldAndFormat> fields;
28+
private final List<FieldAndFormat> fields;
2829

2930
/**
3031
* Create a new FetchDocValuesContext using the provided input list.
@@ -40,7 +41,7 @@ public FetchDocValuesContext(SearchExecutionContext searchExecutionContext, List
4041
fieldToFormats.put(fieldName, new FieldAndFormat(fieldName, field.format, field.includeUnmapped));
4142
}
4243
}
43-
this.fields = fieldToFormats.values();
44+
this.fields = new ArrayList<>(fieldToFormats.values());
4445
int maxAllowedDocvalueFields = searchExecutionContext.getIndexSettings().getMaxDocvalueFields();
4546
if (fields.size() > maxAllowedDocvalueFields) {
4647
throw new IllegalArgumentException(
@@ -58,7 +59,7 @@ public FetchDocValuesContext(SearchExecutionContext searchExecutionContext, List
5859
/**
5960
* Returns the required docvalue fields.
6061
*/
61-
public Collection<FieldAndFormat> fields() {
62+
public List<FieldAndFormat> fields() {
6263
return this.fields;
6364
}
6465
}

0 commit comments

Comments
 (0)