Using the Java ElasticsearchClient, is it possible to create a custom mapper, so that depending on a certain field (or index) of the result hit, a different object is mapped?
I have several indices with different, but very similar documents. The base properties are the same in all of them. And if I query for a list of IDs, I ususally query for (similar) objects in different indices. Ideally I want to have a result list List<? extends BaseDocument>
with potentially different objects in it, all of them extending my BaseDocument
.
Of course, one approach would be to this in my BaseDocument
, which will store all unmapped properties in a map.
@JsonAnyGetter
@JsonAnySetter
protected final Map<String, Object> properties = new LinkedHashMap<>();
And then, in SpecialDocument
, I can access those properties by
public getSpecialProperty() {
return super.properties.get("specialProperty");
}
Another way would be to map all result hits just to a Map
, and then checking the contents of the map and using a custom ObjectMapper
to map this map back to my domain objects:
public List<? extends BaseDocument> search(final List<String> indices, final Query query) throws IOException {
final ObjectMapper objectMapper = new ObjectMapper();
final SearchResponse<Map> searchResponse = elasticsearchClient.search(s -> s.index(indices).query(query), Map.class);
return searchResponse.hits().hits().stream().map(
hit -> {
switch (hit.source().get("documentType").toString()) {
case "specialDocument":
return objectMapper.convertValue(hit.source(), SpecialDocument.class);
case "anotherSpecialDocument":
return objectMapper.convertValue(hit.source(), AnotherSpecialDocument.class);
default:
return new BaseDocument();
}
}
).toList();
}
Now, this is mapping the result twice, one time to a Map
, another time to a concrete object.
Is there a way to pass a mapper to the ElasticsearchClient
(instead of the JsonpMapper
, for example?), where I can define conditions to map the result directly to a certain object, instead of treating all results as the same?