Elasticsearch — переход с Java High Level Rest Client на новый Java API-клиент версии 8.x

Я использую новую версию 8.13 Elasticsearch для нового поискового приложения и пытаюсь имитировать приведенную ниже логику, используя новый клиент Java API вместо использования клиента Java High Level Rest, который сейчас устарел. Мне нужно выполнить поиск по нескольким индексам, включая запросы ниже:

1. Multiple matchPhrasePrefixQuery, как показано ниже.

BoolQueryBuilder searchTheseFields = QueryBuilders.boolQuery();
for (String searchFields : searchTheseFieldsArray) {
        searchTheseFields .should(QueryBuilders.matchPhrasePrefixQuery(searchFields, **SearchText**));
            }

2.запросы с несколькими терминами с полями и значениями

BoolQueryBuilder filterFields = QueryBuilders.boolQuery();
for (Map.Entry<String, Object> entry : filterTheseFields.entrySet()) {
                filterFields.must(QueryBuilders.termQuery(entry.getKey(), entry.getValue()));
            }

3.запросы с несколькими диапазонами

BoolQueryBuilder rangeFilter1 = QueryBuilders.boolQuery();
BoolQueryBuilder rangeFilter2 = QueryBuilders.boolQuery();

rangeFilter1.should(QueryBuilders.rangeQuery(key).gte("gteVal").lte("lteVal"))
                               .should(QueryBuilders.boolQuery().mustNot(QueryBuilders.existsQuery(key)));

И, наконец, добавьте все эти запросы в один построитель запросов, как показано ниже, и вызовите их с помощью client.

BoolQueryBuilder queryBuilder = QueryBuilders.boolQuery()
                .must(searchTheseFields)
                .must(filterFields)
                .filter(rangeFilter1);

SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        searchSourceBuilder.query(queryBuilder);
        searchSourceBuilder.from(data.getFrom());
        searchSourceBuilder.size(data.getSize());
        
SearchRequest searchRequest = new SearchRequest();
        searchRequest.indices(passing indices here);
        searchRequest.source(searchSourceBuilder);
        
SearchResponse response = client.search(searchRequest);

Проблемы, с которыми я сталкиваюсь при попытке использовать новый Java-клиент – Нет BoolQueryBuilder, который использовался ранее для создания запросов разных типов и их агрегирования. Как упомянул @Murat, SearchSourceBuilder также не существует.

Итак, может ли кто-нибудь помочь мне имитировать приведенный выше код, используя новый клиент Java API Elasticsearch новой версии 8 или выше, например, как мы можем создавать несколько запросов разных типов, добавлять их все в один запрос и вызывать его с помощью клиента.

Спасибо

🤔 А знаете ли вы, что...
Java активно развивается и обновляется с появлением новых версий и функциональных улучшений.


1
380
2

Ответы:

Сегодня все время провел с этой темой. Хорошо, сначала вы можете прочитать соответствующую документацию. https://www.elastic.co/guide/en/elasticsearch/client/java-api-client/current/searching.html

Вы можете создавать отдельные запросы, такие как BoolQuery, RangeQuery, MultiMatchQuery, TermQuery и т. д. Тозе находятся в библиотеке по адресу: https://artifacts.elastic.co/javadoc/co/elastic/clients/elasticsearch-java/8.13.2/ co/elastic/clients/elasticsearch/_types/query_dsl/package-summary.html

Некоторые примеры:

String searchText = "bike";
double maxPrice = 200.0;

// Search by product name
Query byName = MatchQuery.of(m -> m 
    .field("name")
    .query(searchText)
)._toQuery(); 

// Search by max price
Query byMaxPrice = RangeQuery.of(r -> r
    .field("price")
    .gte(JsonData.of(maxPrice)) 
)._toQuery();

Вы можете использовать запросы непосредственно внутри client.search(), который возвращает вам ответ от Elasticsearch.

Query aTermQuery = TermQuery.of(tq -> tq.field(myfield).term(myterm)._toQuery();

SearchResponse<MyClass> response = client.search(s -> s.query(q -> q.bool(b -> b
  .must(aTermQuery))), MyClass.class);

Или вы можете создать объект SearchRequest, добавить в него свои запросы и использовать тот же шаблон с client.search().

Query byName = MatchQuery.of(m -> m 
    .field("name")
    .query(searchText)
)._toQuery(); 

SearchRequest mySearchRequest = new SearchRequest.Builder.query(byName).build().
SearchResponse<MyClass> response = client.search(mySearchRequest, MyClass.class);

Могут быть небольшие ошибки, но я думаю, что логика должна быть простой. Удачи.

Обновлено: я не смог найти SearchSourceBuilder в новой библиотеке. Насколько я читал, такого класса нет.


Решено

Наконец, я преобразовал опубликованную выше логику из Elasticsearch 7.16.2 Java High Level Rest Client в новый Java-клиент Elasticsearch 8.13.2.

1.множественное совпадениеPhrasePrefixQuery

BoolQuery.Builder searchTheseFields = new BoolQuery.Builder();
for (String searchFields : searchTheseFieldsArray) {
            searchTheseFields.should(Query.of(q -> q
                    .matchPhrasePrefix(m -> m.field(searchFields).query("searchText"))));
        }

2.запросы с несколькими терминами с полями и значениями

BoolQuery.Builder filterFields = new BoolQuery.Builder();
for (Map.Entry<String, Object> entry : filterFieldsList.entrySet()) {
            filterFields.must(Query.of(
                    q -> q.term(t -> t.field(entry.getKey()).value(entry.getValue().toString().toLowerCase()))));
        }

3.запросы с несколькими диапазонами

ArrayList<Query> rangeFilterQueries = new ArrayList<>();
Query rangeQuery1 = QueryBuilders.range().field(key).gte(JsonData.of(dateRange.get(0)))
                        .lte(JsonData.of(dateRange.get(1))).build()._toQuery();
                Query notExistsQuery1 = QueryBuilders.bool().mustNot(m -> m.exists(e -> e.field(key))).build()
                        ._toQuery();
                rangeFilterQueries
                    .add(QueryBuilders.bool().should(rangeQuery1).should(notExistsQuery1).build()._toQuery()); etc...

Построение окончательного запроса

BoolQuery.Builder queryBuilder = new BoolQuery.Builder().must(searchTheseFields.build()._toQuery())
            .must(filterFields.build()._toQuery());

    for (Query rangeFilterQuery : rangeFilterQueries) {
        queryBuilder.filter(rangeFilterQuery);
    }

    Query finalQuery = queryBuilder.build()._toQuery();

Выполнение запроса

SearchRequest searchRequest = new SearchRequest.Builder().index(indicesToSearchFrom).query(finalQuery)
            .from(offset).size(limit).build();