Я использую новую версию 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 активно развивается и обновляется с появлением новых версий и функциональных улучшений.
Сегодня все время провел с этой темой. Хорошо, сначала вы можете прочитать соответствующую документацию. 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();