Skip to content

Allow field retrieval on placeholder fields #86289

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Apr 29, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,15 @@ public PlaceHolderFieldType(String name, String type, Map<String, String> meta)

@Override
public ValueFetcher valueFetcher(SearchExecutionContext context, String format) {
throw new UnsupportedOperationException("can't fetch values on place holder field type");
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In #85059 I forgot that you're not supposed to throw UnsupportedOperationException here (only allowed for metadata fields) as it will break the fields API.

// ignore format parameter
return new SourceValueFetcher(name(), context) {

@Override
protected Object parseSourceValue(Object value) {
// preserve as is, we can't really do anything smarter than that here
return value;
}
};
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,22 @@

package org.elasticsearch.index.mapper;

import org.apache.lucene.index.LeafReaderContext;
import org.apache.lucene.search.IndexSearcher;
import org.elasticsearch.Version;
import org.elasticsearch.common.Strings;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.index.query.SearchExecutionContext;
import org.elasticsearch.search.lookup.SearchLookup;
import org.elasticsearch.xcontent.XContentBuilder;

import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import static org.hamcrest.Matchers.instanceOf;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class PlaceHolderFieldMapperTests extends MapperServiceTestCase {

Expand All @@ -40,4 +50,26 @@ public void testPreserveParams() throws Exception {
assertThat(service.fieldType("myfield"), instanceOf(PlaceHolderFieldMapper.PlaceHolderFieldType.class));
assertEquals(Strings.toString(mapping), Strings.toString(service.documentMapper().mapping()));
}

public void testFetchValue() throws Exception {
MapperService mapperService = createMapperService(Version.fromString("5.0.0"), fieldMapping(b -> b.field("type", "unknown")));
withLuceneIndex(mapperService, iw -> {
iw.addDocument(
createMapperService(fieldMapping(b -> b.field("type", "keyword"))).documentMapper()
.parse(source(b -> b.field("field", "value")))
.rootDoc()
);
}, iw -> {
SearchLookup lookup = new SearchLookup(mapperService::fieldType, fieldDataLookup());
SearchExecutionContext searchExecutionContext = mock(SearchExecutionContext.class);
when(searchExecutionContext.lookup()).thenReturn(lookup);
when(searchExecutionContext.sourcePath("field")).thenReturn(Set.of("field"));
ValueFetcher valueFetcher = mapperService.fieldType("field").valueFetcher(searchExecutionContext, null);
IndexSearcher searcher = newSearcher(iw);
LeafReaderContext context = searcher.getIndexReader().leaves().get(0);
lookup.source().setSegmentAndDocument(context, 0);
valueFetcher.setNextReader(context);
assertEquals(List.of("value"), valueFetcher.fetchValues(lookup.source(), new ArrayList<>()));
});
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,7 @@ public void setupIndex() throws IOException {
.startObject("apache2")
.startObject("access")
.field("url", "myurl1")
.field("agent", "agent1")
.endObject()
.endObject()
.endObject();
Expand All @@ -111,6 +112,7 @@ public void setupIndex() throws IOException {
.startObject("apache2")
.startObject("access")
.field("url", "myurl2")
.field("agent", "agent2")
.endObject()
.endObject()
.endObject();
Expand Down Expand Up @@ -228,4 +230,28 @@ public void testAggregationOnPlaceholderField() throws IOException {
assertThat(re.getMessage(), containsString("can't run aggregation or sorts on field type text of legacy index"));
}

public void testSearchFieldsOnPlaceholderField() throws IOException {
Request search = new Request("POST", "/" + "filebeat" + "/_search");
XContentBuilder query = XContentBuilder.builder(XContentType.JSON.xContent())
.startObject()
.startObject("query")
.startObject("match")
.startObject("apache2.access.url")
.field("query", "myurl2")
.endObject()
.endObject()
.endObject()
.startArray("fields")
.value("apache2.access.agent")
.endArray()
.endObject();
search.setJsonEntity(Strings.toString(query));
Map<String, Object> response = entityAsMap(client().performRequest(search));
List<?> hits = (List<?>) (XContentMapValues.extractValue("hits.hits", response));
assertThat(hits, hasSize(1));
logger.info(hits);
Map<?, ?> fields = (Map<?, ?>) (XContentMapValues.extractValue("fields", (Map<?, ?>) hits.get(0)));
assertEquals(List.of("agent2"), fields.get("apache2.access.agent"));
}

}