#hibernate #elasticsearch #hibernate-search
Вопрос:
Я кодирую простой запрос, ориентированный на несколько индексов :
//targetIndexes is a list of indexes
searchSession.search(targetIndexes).extension(ElasticsearchExtension.get())
Теперь я просто хочу «countByDocumentType». Это означает, что я хочу, чтобы количество результатов было сгруппировано по типу индекса. Для этого у меня уже есть два поля в моем сохраненном индексе, но я не могу запросить их с помощью поиска в режиме гибернации, черт возьми !
На самом деле, эластичный поиск добавляет свое собственное поле с именем «_index», чтобы разрешить фильтрацию по индексу. Поиск в режиме гибернации добавляет также собственное поле с именем «_entity_type». Но я не могу запрашивать «_index» или «_entity_type» с помощью поиска в режиме гибернации, используя агрегацию, подобную этой :
AggregationKey<Map<String, Long>> countsByEntityKey = AggregationKey.of( "countsByEntity" );
...where(...).aggregation(countsByEntityKey, f -> f.terms()
.field( "_entity_type", String.class ));
Так действительно ли мне нужно загрязнять все мои классы, добавляя пользовательское третье поле в каждую сопоставленную сущность hibernate, чтобы иметь возможность выполнять запросы по определенному индексу ?
@Indexed
public class MyIndexedEntity {
...
@GenericField
public String getEntityName() {
return this.getClass.getName();
}
}
Спасибо за ваш ответ
Ответ №1:
Вы не можете ссылаться на поля, которые еще не являются частью сопоставления поиска в режиме гибернации в DSL поиска в режиме гибернации.
Я бы предложил использовать собственную агрегацию:
AggregationKey<JsonObject> countsByEntityTypeKey = AggregationKey.of( "countsByEntityType" );
SearchResult<Book> result = searchSession.search( Arrays.asList( Book.class, Author.class ) )
.extension( ElasticsearchExtension.get() )
.where( f -> f.matchAll() )
.aggregation( countsByEntityTypeKey, f -> f.fromJson( "{"terms":{"field": "_entity_type"}}" ) )
.fetch( 20 );
JsonObject countsByEntityTypeAsJson = result.aggregation( countsByEntityTypeKey );
Map<String, Long> countsByEntityType = new HashMap<>();
for ( JsonElement bucket: countsByEntityTypeAsJson.get("buckets").getAsJsonArray() ) {
JsonObject bucketObject = bucket.getAsJsonObject();
countsByEntityType.put( bucketObject.get( "key" ).getAsString(),
bucketObject.get( "doc_count" ).getAsLong() );
}
Вы все еще можете использовать (менее подробный) Гибернируйте API-интерфейсы поиска для всего остального в том же запросе.
Комментарии:
1. Спасибо вам за ваш ответ. Я как раз собирался опубликовать тот же ответ, я нашел его так же, как и вы. Приятно, что можно включить «конкретный» режим с помощью эластичного метода FromJSON. Низкоуровневый api позволяет это сделать. Спасибо!