Skip to content

Commit 425be6a

Browse files
authored
Allow field retrieval on placeholder fields (#86289)
Integrates the fields API with placeholder fields. Relates #81210
1 parent 70d2d6a commit 425be6a

File tree

3 files changed

+67
-1
lines changed

3 files changed

+67
-1
lines changed

server/src/main/java/org/elasticsearch/index/mapper/PlaceHolderFieldMapper.java

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -114,7 +114,15 @@ public PlaceHolderFieldType(String name, String type, Map<String, String> meta)
114114

115115
@Override
116116
public ValueFetcher valueFetcher(SearchExecutionContext context, String format) {
117-
throw new UnsupportedOperationException("can't fetch values on place holder field type");
117+
// ignore format parameter
118+
return new SourceValueFetcher(name(), context) {
119+
120+
@Override
121+
protected Object parseSourceValue(Object value) {
122+
// preserve as is, we can't really do anything smarter than that here
123+
return value;
124+
}
125+
};
118126
}
119127

120128
@Override

server/src/test/java/org/elasticsearch/index/mapper/PlaceHolderFieldMapperTests.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,12 +8,22 @@
88

99
package org.elasticsearch.index.mapper;
1010

11+
import org.apache.lucene.index.LeafReaderContext;
12+
import org.apache.lucene.search.IndexSearcher;
1113
import org.elasticsearch.Version;
1214
import org.elasticsearch.common.Strings;
1315
import org.elasticsearch.common.settings.Settings;
16+
import org.elasticsearch.index.query.SearchExecutionContext;
17+
import org.elasticsearch.search.lookup.SearchLookup;
1418
import org.elasticsearch.xcontent.XContentBuilder;
1519

20+
import java.util.ArrayList;
21+
import java.util.List;
22+
import java.util.Set;
23+
1624
import static org.hamcrest.Matchers.instanceOf;
25+
import static org.mockito.Mockito.mock;
26+
import static org.mockito.Mockito.when;
1727

1828
public class PlaceHolderFieldMapperTests extends MapperServiceTestCase {
1929

@@ -40,4 +50,26 @@ public void testPreserveParams() throws Exception {
4050
assertThat(service.fieldType("myfield"), instanceOf(PlaceHolderFieldMapper.PlaceHolderFieldType.class));
4151
assertEquals(Strings.toString(mapping), Strings.toString(service.documentMapper().mapping()));
4252
}
53+
54+
public void testFetchValue() throws Exception {
55+
MapperService mapperService = createMapperService(Version.fromString("5.0.0"), fieldMapping(b -> b.field("type", "unknown")));
56+
withLuceneIndex(mapperService, iw -> {
57+
iw.addDocument(
58+
createMapperService(fieldMapping(b -> b.field("type", "keyword"))).documentMapper()
59+
.parse(source(b -> b.field("field", "value")))
60+
.rootDoc()
61+
);
62+
}, iw -> {
63+
SearchLookup lookup = new SearchLookup(mapperService::fieldType, fieldDataLookup());
64+
SearchExecutionContext searchExecutionContext = mock(SearchExecutionContext.class);
65+
when(searchExecutionContext.lookup()).thenReturn(lookup);
66+
when(searchExecutionContext.sourcePath("field")).thenReturn(Set.of("field"));
67+
ValueFetcher valueFetcher = mapperService.fieldType("field").valueFetcher(searchExecutionContext, null);
68+
IndexSearcher searcher = newSearcher(iw);
69+
LeafReaderContext context = searcher.getIndexReader().leaves().get(0);
70+
lookup.source().setSegmentAndDocument(context, 0);
71+
valueFetcher.setNextReader(context);
72+
assertEquals(List.of("value"), valueFetcher.fetchValues(lookup.source(), new ArrayList<>()));
73+
});
74+
}
4375
}

x-pack/qa/repository-old-versions/src/test/java/org/elasticsearch/oldrepos/OldMappingsIT.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -98,6 +98,7 @@ public void setupIndex() throws IOException {
9898
.startObject("apache2")
9999
.startObject("access")
100100
.field("url", "myurl1")
101+
.field("agent", "agent1")
101102
.endObject()
102103
.endObject()
103104
.endObject();
@@ -111,6 +112,7 @@ public void setupIndex() throws IOException {
111112
.startObject("apache2")
112113
.startObject("access")
113114
.field("url", "myurl2")
115+
.field("agent", "agent2")
114116
.endObject()
115117
.endObject()
116118
.endObject();
@@ -228,4 +230,28 @@ public void testAggregationOnPlaceholderField() throws IOException {
228230
assertThat(re.getMessage(), containsString("can't run aggregation or sorts on field type text of legacy index"));
229231
}
230232

233+
public void testSearchFieldsOnPlaceholderField() throws IOException {
234+
Request search = new Request("POST", "/" + "filebeat" + "/_search");
235+
XContentBuilder query = XContentBuilder.builder(XContentType.JSON.xContent())
236+
.startObject()
237+
.startObject("query")
238+
.startObject("match")
239+
.startObject("apache2.access.url")
240+
.field("query", "myurl2")
241+
.endObject()
242+
.endObject()
243+
.endObject()
244+
.startArray("fields")
245+
.value("apache2.access.agent")
246+
.endArray()
247+
.endObject();
248+
search.setJsonEntity(Strings.toString(query));
249+
Map<String, Object> response = entityAsMap(client().performRequest(search));
250+
List<?> hits = (List<?>) (XContentMapValues.extractValue("hits.hits", response));
251+
assertThat(hits, hasSize(1));
252+
logger.info(hits);
253+
Map<?, ?> fields = (Map<?, ?>) (XContentMapValues.extractValue("fields", (Map<?, ?>) hits.get(0)));
254+
assertEquals(List.of("agent2"), fields.get("apache2.access.agent"));
255+
}
256+
231257
}

0 commit comments

Comments
 (0)