Агрегация поиска в режиме гибернации : тип countbydocument (с серверной частью elaticsearch)

#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 позволяет это сделать. Спасибо!