Вот мой текущий репозиторий BookSearch:
Код: Выделить всё
package com.search.elasticsearch.infrastructure;
import co.elastic.clients.elasticsearch._types.SortOrder;
import co.elastic.clients.elasticsearch._types.query_dsl.MatchQuery;
import com.search.elasticsearch.document.BookDocument;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.elasticsearch.client.elc.NativeQuery;
import org.springframework.data.elasticsearch.client.elc.NativeQueryBuilder;
import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.stereotype.Repository;
@Repository
@RequiredArgsConstructor
public class BookSearchRepository {
private final ElasticsearchOperations elasticsearchOperations;
public SearchHits searchBooksByTitle(
String title,
int size,
Long previousTimestamp,
String previousTieBreakerId
) {
NativeQueryBuilder nativeQueryBuilder = new NativeQueryBuilder()
.withQuery(new MatchQuery.Builder()
.field("title")
.query(title)
.build()._toQuery())
.withSort(sort -> sort
.field(f -> f.field("updated_at").order(SortOrder.Asc)))
.withSort(sort -> sort
.field(f -> f.field("tie_breaker_id").order(SortOrder.Asc)))
.withMaxResults(size + 1);
if (previousTimestamp != null && previousTieBreakerId != null) {
nativeQueryBuilder.withSearchAfter(List.of(previousTimestamp, previousTieBreakerId));
}
NativeQuery nativeSearchQuery = nativeQueryBuilder.build();
return elasticsearchOperations.search(nativeSearchQuery, BookDocument.class);
}
}
Код: Выделить всё
package com.search.elasticsearch.application;
import com.search.book.dto.BookOutline;
import com.search.elasticsearch.document.BookDocument;
import com.search.elasticsearch.dto.response.BookSearchResponse;
import com.search.elasticsearch.infrastructure.BookSearchRepository;
import com.search.mapper.BookMapper;
import java.util.List;
import lombok.RequiredArgsConstructor;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.stereotype.Service;
@Service
@RequiredArgsConstructor
public class SearchService {
private final BookSearchRepository bookSearchRepository;
private final BookMapper bookMapper;
public BookSearchResponse searchBooksByTitle(
int size,
String title,
long lastUnixTimestamp,
String lastTieBreakerId
) {
List searchHits = bookSearchRepository.searchBooksByTitle(
title,
size,
lastUnixTimestamp,
lastTieBreakerId
).getSearchHits();
int searchHitsSize = searchHits.size();
boolean hasMore = searchHitsSize > size;
if (hasMore) {
searchHitsSize--;
}
List sortValues = searchHits.get(searchHitsSize - 1).getSortValues();
Long previousUnixTimestamp = (Long) sortValues.get(0);
String previousTieBreakerId = (String) sortValues.get(1);
List bookOutlines = searchHits.stream()
.map(hit -> bookMapper.toBookOutline(hit.getContent()))
.limit(size)
.toList();
return new BookSearchResponse(
hasMore,
previousUnixTimestamp,
previousTieBreakerId,
bookOutlines
);
}
}
Уместно ли возвращать SearchHits из уровня репозитория?
Я реализовал BookDocumentRepository с помощью ElasticsearchOperations и NativeQueryBuilder, чтобы создать собственный запрос для поиска книг по названию. Я ожидал, что этот подход позволит мне эффективно реализовать бесконечную прокрутку с помощью параметра search_after.
Подробнее здесь: https://stackoverflow.com/questions/790 ... n-spring-b
Мобильная версия