To search with one query for several indexes in "Spring Data ES", I created an object "IndexCoordinates", in which I added the names of the indexes I needed. The result is expected. At the same time, the evaluation of the document for compliance with the request is determined by the totality of the results, and not by each index separately. But I ran into a problem: some documents of the query result are defined as the type of the corresponding user class, but some are defined as "LinkedHashMap". At the same time, there is no such situation for any other query for each index separately. My "IndexCoordinates" looks like this:
final static IndexCoordinates ALIAS_INDEX_COORDINATES = IndexCoordinates.of("directors_index", "actors_index", "native_film_index","serial_index");
The request code is as follows:
Query query = NativeQuery.builder()
.withQuery(q -> q.functionScore(f -> f
.functions(fu -> fu.fieldValueFactor(fvf -> fvf
.field("booster")
.modifier(FieldValueFactorModifier.Log2p)
.missing(0.0)
))
.query(fq -> fq.
bool(b -> {
if (titleInLowercase.equals("")) {
b.must(m -> m.matchAll(ma -> ma));
} else if ((titleInLowercase.length()) >= 2) {
// for "directors_index", "actors_index"
b.should(s -> s
.match(m -> m
.field("name")
.query(titleInLowercase)));
// for "native_film_index","serial_index"
b.should(s -> s
.match(m -> m
.field("title")
.query(titleInLowercase)));
}
if (!frontRequest.isNull("language") && finalValueListLanguage.size() == 1) { b.filter(bf -> bf... }
if (!frontRequest.isNull("countries") && finalValueListCountries.size() == 1) { b.filter(bf -> bf... }
.....
return b;
}))))
.withPageable(Pageable.ofSize(pageSize))
.build();
SearchHits<Object> filmSearchHits = operations.search(query, Object.class, indexCoordinates);
List<Object> searchResult = filmSearchHits.stream().map(SearchHit::getContent).toList();
Next, each document must be converted to the corresponding DTO, based on the class of the received document (a certain user type is expected). But in some cases, a "LinkedHashMap" is issued, and not the one I expect, and it is not possible to form a "DTO", because the method generates a "DTO" object from an doc of the corresponding user type. How to convert an object from "LinkedHashMap" to the desired class is an unnecessary question of another topic. Please help me understand how the "LinkedHashMap" occurs, and how to avoid it if it possible. Initially, objects are added to the index as a JSONObject.
If you tell Spring Data Elasticsearch to return entities of type
Object, you get just some objects. And aMap<String, Object>is basically the only thing that a returned JSON value can be converted to.The concept of Spring Data is based on entitties and repositories, each of which stores one entity.
What you try to achieve is to read many different entity types in one call and expect Spring Data Elasticsearch to know how to convert the returned data into the different entity instances.
This is not done by Spring Data Elasticsearch, but you can implement some logic by yourself that handles that. Back in May 2021 I wrote a blog post showing how this can be implemented.