Skip to content

Commit d7219c0

Browse files
authored
Search: Support of wildcard on docvalue_fields (#32980)
* Search: Support of wildcard on docvalue_fields For consistency with stored_fields, docvalue_fields should support the use of wildcards. Documentation of doc values fields is updated accordingly. See also: #26390 Closes #26299
1 parent ffe895e commit d7219c0

File tree

3 files changed

+125
-5
lines changed

3 files changed

+125
-5
lines changed

docs/reference/search/request/docvalue-fields.asciidoc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,27 @@ GET /_search
3030

3131
Doc value fields can work on fields that are not stored.
3232

33+
`*` can be used as a wild card, for example:
34+
35+
[source,js]
36+
--------------------------------------------------
37+
GET /_search
38+
{
39+
"query" : {
40+
"match_all": {}
41+
},
42+
"docvalue_fields" : [
43+
{
44+
"field": "*field", <1>
45+
"format": "use_field_mapping" <2>
46+
}
47+
]
48+
}
49+
--------------------------------------------------
50+
// CONSOLE
51+
<1> Match all fields ending with `field`
52+
<2> Format to be applied to all matching fields.
53+
3354
Note that if the fields parameter specifies fields without docvalues it will try to load the value from the fielddata cache
3455
causing the terms for that field to be loaded to memory (cached), which will result in more memory consumption.
3556

server/src/main/java/org/elasticsearch/search/SearchService.java

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,8 @@
9898
import org.elasticsearch.transport.TransportRequest;
9999

100100
import java.io.IOException;
101+
import java.util.ArrayList;
102+
import java.util.Collection;
101103
import java.util.Collections;
102104
import java.util.HashMap;
103105
import java.util.List;
@@ -789,14 +791,21 @@ private void parseSource(DefaultSearchContext context, SearchSourceBuilder sourc
789791
context.fetchSourceContext(source.fetchSource());
790792
}
791793
if (source.docValueFields() != null) {
794+
List<DocValueFieldsContext.FieldAndFormat> docValueFields = new ArrayList<>();
795+
for (DocValueFieldsContext.FieldAndFormat format : source.docValueFields()) {
796+
Collection<String> fieldNames = context.mapperService().simpleMatchToFullName(format.field);
797+
for (String fieldName: fieldNames) {
798+
docValueFields.add(new DocValueFieldsContext.FieldAndFormat(fieldName, format.format));
799+
}
800+
}
792801
int maxAllowedDocvalueFields = context.mapperService().getIndexSettings().getMaxDocvalueFields();
793-
if (source.docValueFields().size() > maxAllowedDocvalueFields) {
802+
if (docValueFields.size() > maxAllowedDocvalueFields) {
794803
throw new IllegalArgumentException(
795-
"Trying to retrieve too many docvalue_fields. Must be less than or equal to: [" + maxAllowedDocvalueFields
796-
+ "] but was [" + source.docValueFields().size() + "]. This limit can be set by changing the ["
797-
+ IndexSettings.MAX_DOCVALUE_FIELDS_SEARCH_SETTING.getKey() + "] index level setting.");
804+
"Trying to retrieve too many docvalue_fields. Must be less than or equal to: [" + maxAllowedDocvalueFields
805+
+ "] but was [" + docValueFields.size() + "]. This limit can be set by changing the ["
806+
+ IndexSettings.MAX_DOCVALUE_FIELDS_SEARCH_SETTING.getKey() + "] index level setting.");
798807
}
799-
context.docValueFieldsContext(new DocValueFieldsContext(source.docValueFields()));
808+
context.docValueFieldsContext(new DocValueFieldsContext(docValueFields));
800809
}
801810
if (source.highlighter() != null) {
802811
HighlightBuilder highlightBuilder = source.highlighter();

server/src/test/java/org/elasticsearch/search/fields/SearchFieldsIT.java

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -810,6 +810,32 @@ public void testDocValueFields() throws Exception {
810810
equalTo(new BytesRef(new byte[] {42, 100})));
811811
assertThat(searchResponse.getHits().getAt(0).getFields().get("ip_field").getValue(), equalTo("::1"));
812812

813+
builder = client().prepareSearch().setQuery(matchAllQuery())
814+
.addDocValueField("*field");
815+
searchResponse = builder.execute().actionGet();
816+
817+
assertThat(searchResponse.getHits().getTotalHits(), equalTo(1L));
818+
assertThat(searchResponse.getHits().getHits().length, equalTo(1));
819+
fields = new HashSet<>(searchResponse.getHits().getAt(0).getFields().keySet());
820+
assertThat(fields, equalTo(newHashSet("byte_field", "short_field", "integer_field", "long_field",
821+
"float_field", "double_field", "date_field", "boolean_field", "text_field", "keyword_field",
822+
"binary_field", "ip_field")));
823+
824+
assertThat(searchResponse.getHits().getAt(0).getFields().get("byte_field").getValue().toString(), equalTo("1"));
825+
assertThat(searchResponse.getHits().getAt(0).getFields().get("short_field").getValue().toString(), equalTo("2"));
826+
assertThat(searchResponse.getHits().getAt(0).getFields().get("integer_field").getValue(), equalTo((Object) 3L));
827+
assertThat(searchResponse.getHits().getAt(0).getFields().get("long_field").getValue(), equalTo((Object) 4L));
828+
assertThat(searchResponse.getHits().getAt(0).getFields().get("float_field").getValue(), equalTo((Object) 5.0));
829+
assertThat(searchResponse.getHits().getAt(0).getFields().get("double_field").getValue(), equalTo((Object) 6.0d));
830+
dateField = searchResponse.getHits().getAt(0).getFields().get("date_field").getValue();
831+
assertThat(dateField.toInstant().toEpochMilli(), equalTo(date.toInstant().toEpochMilli()));
832+
assertThat(searchResponse.getHits().getAt(0).getFields().get("boolean_field").getValue(), equalTo((Object) true));
833+
assertThat(searchResponse.getHits().getAt(0).getFields().get("text_field").getValue(), equalTo("foo"));
834+
assertThat(searchResponse.getHits().getAt(0).getFields().get("keyword_field").getValue(), equalTo("foo"));
835+
assertThat(searchResponse.getHits().getAt(0).getFields().get("binary_field").getValue(),
836+
equalTo(new BytesRef(new byte[] {42, 100})));
837+
assertThat(searchResponse.getHits().getAt(0).getFields().get("ip_field").getValue(), equalTo("::1"));
838+
813839
builder = client().prepareSearch().setQuery(matchAllQuery())
814840
.addDocValueField("text_field", "use_field_mapping")
815841
.addDocValueField("keyword_field", "use_field_mapping")
@@ -977,6 +1003,70 @@ public void testDocValueFieldsWithFieldAlias() throws Exception {
9771003
assertThat(fetchedDate, equalTo(date));
9781004
}
9791005

1006+
public void testWildcardDocValueFieldsWithFieldAlias() throws Exception {
1007+
XContentBuilder mapping = XContentFactory.jsonBuilder()
1008+
.startObject()
1009+
.startObject("type")
1010+
.startObject("_source")
1011+
.field("enabled", false)
1012+
.endObject()
1013+
.startObject("properties")
1014+
.startObject("text_field")
1015+
.field("type", "text")
1016+
.field("fielddata", true)
1017+
.endObject()
1018+
.startObject("date_field")
1019+
.field("type", "date")
1020+
.field("format", "yyyy-MM-dd")
1021+
.endObject()
1022+
.startObject("text_field_alias")
1023+
.field("type", "alias")
1024+
.field("path", "text_field")
1025+
.endObject()
1026+
.startObject("date_field_alias")
1027+
.field("type", "alias")
1028+
.field("path", "date_field")
1029+
.endObject()
1030+
.endObject()
1031+
.endObject()
1032+
.endObject();
1033+
assertAcked(prepareCreate("test").addMapping("type", mapping));
1034+
ensureGreen("test");
1035+
1036+
ZonedDateTime date = ZonedDateTime.of(1990, 12, 29, 0, 0, 0, 0, ZoneOffset.UTC);
1037+
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd", Locale.ROOT);
1038+
1039+
index("test", "type", "1", "text_field", "foo", "date_field", formatter.format(date));
1040+
refresh("test");
1041+
1042+
SearchRequestBuilder builder = client().prepareSearch().setQuery(matchAllQuery())
1043+
.addDocValueField("*alias", "use_field_mapping")
1044+
.addDocValueField("date_field");
1045+
SearchResponse searchResponse = builder.execute().actionGet();
1046+
1047+
assertNoFailures(searchResponse);
1048+
assertHitCount(searchResponse, 1);
1049+
SearchHit hit = searchResponse.getHits().getAt(0);
1050+
1051+
Map<String, DocumentField> fields = hit.getFields();
1052+
assertThat(fields.keySet(), equalTo(newHashSet("text_field_alias", "date_field_alias", "date_field")));
1053+
1054+
DocumentField textFieldAlias = fields.get("text_field_alias");
1055+
assertThat(textFieldAlias.getName(), equalTo("text_field_alias"));
1056+
assertThat(textFieldAlias.getValue(), equalTo("foo"));
1057+
1058+
DocumentField dateFieldAlias = fields.get("date_field_alias");
1059+
assertThat(dateFieldAlias.getName(), equalTo("date_field_alias"));
1060+
assertThat(dateFieldAlias.getValue(),
1061+
equalTo("1990-12-29"));
1062+
1063+
DocumentField dateField = fields.get("date_field");
1064+
assertThat(dateField.getName(), equalTo("date_field"));
1065+
1066+
ZonedDateTime fetchedDate = dateField.getValue();
1067+
assertThat(fetchedDate, equalTo(date));
1068+
}
1069+
9801070

9811071
public void testStoredFieldsWithFieldAlias() throws Exception {
9821072
XContentBuilder mapping = XContentFactory.jsonBuilder()

0 commit comments

Comments
 (0)