How to set result size zero in spring data elastic

2019-07-06 05:31发布

问题:

Consider the following elasticsearch query :

{
  "query": {"match_all": {}},
  "size": 0, 
  "aggs": {
      "Terms": { "terms": { "field":"fileName" }
      }
   }
}

Here I'm just interested in the aggregation and not in the documents. That's why I set size:0 and it works as expected. However I'm unable to achieve the same with spring-data. Code sample :

PageRequest page = new PageRequest(0, 0);
SearchQuery searchQuery = new NativeSearchQueryBuilder()
                .withIndices(indexName).withTypes(typeName)
                .withQuery(queryBuilder).withAggregation(aggsBuilder)
                .withPageable(pageable).build();

This PageRequest constructor throws an exception then, which is from its parent:

public AbstractPageRequest(int page, int size) {
    if (page < 0) {
        throw new IllegalArgumentException("Page index must not be less than zero!");
    }
    if (size < 1) {
        throw new IllegalArgumentException("Page size must not be less than one!");
    }
    this.page = page;
    this.size = size;
}

Question : Is there any way in spring data to limit document size to zero ?

回答1:

We can define empty pageable interface implementation class, like this:

public static class EmptyPage implements Pageable {
    public static final EmptyPage INSTANCE = new EmptyPage();

    @Override
    public int getPageNumber() {
        return 0;
    }

    @Override
    public int getPageSize() {
        return 0;
    }

    @Override
    public int getOffset() {
        return 0;
    }

    @Override
    public Sort getSort() {
        return null;
    }

    @Override
    public Pageable next() {
        return null;
    }

    @Override
    public Pageable previousOrFirst() {
        return null;
    }

    @Override
    public Pageable first() {
        return null;
    }

    @Override
    public boolean hasPrevious() {
        return false;
    }
}

Use:

    SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withQuery(queryBuilder)
            .withIndices(indexName).withTypes(typeName)
            .addAggregation(aggsBuilder)
            .withPageable(EmptyPage.INSTANCE)
            .build();

Result:

{
  "aggregations": { ... },
  "from": 0,
  "query": { ... },
  "size": 0
}


回答2:

If you're using ES 1.x, what you can do is leave out the Pageable and specify the search type COUNT instead.

SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withIndices(indexName).withTypes(typeName)
            .withQuery(queryBuilder).withAggregation(aggsBuilder)
            .withSearchType(SearchType.COUNT).build();

As of ES 2.x, SearchType.COUNT will be deprecated and not available anymore, but for ES 1.x needs this should do the job.

Note that there's a similar need for other users, too, but the issue is still open.



回答3:

This is a bit late, but may be of use for future developers. The way for me was to define a new class PageRequest that implements org.springframework.data.domain.Pageable and the resembles org.springframework.data.domain.PageRequest but does not have constraints of AbstractPageRequest on size.
Then you can pass it to your builder.



回答4:

I think what you want is to set "size": 0 in code?

Paging is not supported in aggregations, so the PageRequest will not be entertained. The error is because page limit cannot be 0. What you need is:

        SearchQuery searchQuery = new NativeSearchQueryBuilder()
                        .withIndices(indexName).withTypes(typeName)
                        .withQuery(queryBuilder)
                        .withAggregation(aggsBuilder.size(0)) //set the size with AggregationBuilders
                        .withSearchType(SearchType.COUNT)                        
                        .build();