使用弹簧数据使用弹性搜索存储库执行分面搜索?

时间:2015-09-16 07:57:02

标签: spring elasticsearch spring-data spring-data-elasticsearch

我需要使用弹簧数据开发的弹性搜索存储库执行分面搜索。

我创建的其中一个存储库是

public interface EmployeeSearchRepository extends ElasticsearchRepository<Employee, Long> { }

它提供了一个名为search的方法,带有签名:

FacetedPage<Employee> search(QueryBuilder query, Pageable pageable);

但FacetedPage的getFacets方法返回null。如何查询以生成构面?

1 个答案:

答案 0 :(得分:1)

我遇到了同样的问题,似乎还没有实现。 如果查看DefaultResultMapper.mapResults(),它会调用始终为null的response.getFacets()。

请注意,在elasticsearch中不推荐使用构面,您应该使用聚合。那么项目的贡献者可能正在重构它吗?

我通过编写自己的结果mapper类来扩展DefaultResultMapper,但也将聚合转换为FacetResults。

SomethingResultsMapper:

@Override
    public <T> FacetedPage<T> mapResults(SearchResponse response, Class<T> clazz, Pageable pageable) {
        FacetedPage<T> facetedPage = super.mapResults(response, clazz, pageable);
        //Process Aggregations.
        if (response.getAggregations() != null) {
            for (Aggregation aggregations : response.getAggregations().asList()) {

                final Filter filterAggregations = (Filter) aggregations;
                for (Aggregation filterAgg : filterAggregations.getAggregations().asList()) {
                    if (filterAgg instanceof Terms) {
                        final Terms aggTerm = (Terms) filterAgg;
                        if (!aggTerm.getBuckets().isEmpty()) {
                            facetedPage.getFacets().add(processTermAggregation(aggTerm));
                        }
                    } else if (filterAgg instanceof Nested) {
                        final Nested nestedAgg = (Nested) filterAgg;
                        for (Aggregation aggregation : nestedAgg.getAggregations().asList()) {
                            final Terms aggTerm = (Terms) aggregation;
                            if (!aggTerm.getBuckets().isEmpty()) {
                                facetedPage.getFacets().add(processTermAggregation(aggTerm));
                            }
                        }
                    } else {
                        throw new IllegalArgumentException("Aggregation type not (yet) supported: " + filterAgg.getClass().getName());
                    }
                }
            }
        }
        return facetedPage;
    }

    private FacetResult processTermAggregation(final Terms aggTerm) {
        long total = 0;
        List<Term> terms = new ArrayList<>();
        List<Terms.Bucket> buckets = aggTerm.getBuckets();
        for (Terms.Bucket bucket : buckets) {
            terms.add(new Term(bucket.getKey(), (int) bucket.getDocCount()));
            total += bucket.getDocCount();
        }
        return new FacetTermResult(aggTerm.getName(), FacetConfig.fromAggregationTerm(aggTerm.getName()).getLabel(),
                terms, total, aggTerm.getSumOfOtherDocCounts(), aggTerm.getDocCountError());
    }

然后我创建了一个自定义Spring数据存储库(参见文档)并定义了一个自定义方法,我提供了SomethingResultsMapper:

@Override
public FacetedPage<Something> searchSomething(final SearchQuery searchQuery) {
    return elasticsearchTemplate.queryForPage(searchQuery, Something.class, new SomethingResultsMapper());
}

编辑:我认为这个问题正由https://jira.spring.io/browse/DATAES-211确定