Текущий ответ с наивысшим рангом работает, но требует загрузки всего списка результатов в памяти, что может вызвать проблемы с памятью для больших наборов результатов и в любом случае не нужно.
Я создал класс Java, который реализует хороший Iterator
по сравнению с SearchHit
s, что позволяет выполнять итерацию по всем результатам. Внутренне он обрабатывает разбиение на страницы путем выпуска запросов, которые включают поле from:
, и он хранит только в памяти на одной странице из результатов.
Использование:
// build your query here -- no need for setFrom(int)
SearchRequestBuilder requestBuilder = client.prepareSearch(indexName)
.setTypes(typeName)
.setQuery(QueryBuilders.matchAllQuery())
SearchHitIterator hitIterator = new SearchHitIterator(requestBuilder);
while (hitIterator.hasNext()) {
SearchHit hit = hitIterator.next();
// process your hit
}
Обратите внимание, что при создании вашего SearchRequestBuilder
, вам не нужно вызывать setFrom(int)
, так как это будет сделано interally по SearchHitIterator
. Если вы хотите указать размер страницы (то есть количество поисковых запросов на страницу), вы можете позвонить setSize(int)
, в противном случае используется значение по умолчанию ElasticSearch.
SearchHitIterator:
import java.util.Iterator;
import org.elasticsearch.action.search.SearchRequestBuilder;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.search.SearchHit;
public class SearchHitIterator implements Iterator<SearchHit> {
private final SearchRequestBuilder initialRequest;
private int searchHitCounter;
private SearchHit[] currentPageResults;
private int currentResultIndex;
public SearchHitIterator(SearchRequestBuilder initialRequest) {
this.initialRequest = initialRequest;
this.searchHitCounter = 0;
this.currentResultIndex = -1;
}
@Override
public boolean hasNext() {
if (currentPageResults == null || currentResultIndex + 1 >= currentPageResults.length) {
SearchRequestBuilder paginatedRequestBuilder = initialRequest.setFrom(searchHitCounter);
SearchResponse response = paginatedRequestBuilder.execute().actionGet();
currentPageResults = response.getHits().getHits();
if (currentPageResults.length < 1) return false;
currentResultIndex = -1;
}
return true;
}
@Override
public SearchHit next() {
if (!hasNext()) return null;
currentResultIndex++;
searchHitCounter++;
return currentPageResults[currentResultIndex];
}
}
В самом деле, понимая, насколько это удобно иметь такой класс, интересно, почему Java-клиент ElasticSearch не предлагает что-то подобное.
У меня также такая же проблема. Thans для вашего вопроса –
У меня есть 100 документов. Я устанавливаю Integer.MAX_VALUE как size.Got OutOfMemoryError [Java heap space] также в My Jboss. Если я даю 1000, то работал нормально. –