创建加速搜索查询elasticsearch

时间:2016-06-24 10:22:11

标签: java elasticsearch spring-boot spring-data-elasticsearch

我需要更改当前的代码搜索,因为它看起来太慢,一次搜索大约需要15秒。

我们正在寻找参数

?uids=1,2

我有这段代码:

private NativeSearchQueryBuilder getSearchQuery(AuctionIndexSearchParams searchParams, Pageable pageable) {
        final List<FilterBuilder> filters = Lists.newArrayList();
        final NativeSearchQueryBuilder searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery());

        Optional.ofNullable(searchParams.getCategoryId()).ifPresent(v -> filters.add(boolFilter().must(termFilter("cat", v))));
        Optional.ofNullable(searchParams.getCurrency()).ifPresent(v -> filters.add(boolFilter().must(termFilter("curr", v))));
        Optional.ofNullable(searchParams.getTreeCategoryId()).ifPresent(v -> filters.add(boolFilter().must(termFilter("tcat", v))));
        Optional.ofNullable(searchParams.getUid()).ifPresent(v -> filters.add(boolFilter().must(termFilter("uid", v))));
        final BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        //access for many uids
        if (searchParams.getUids() != null) {
            Optional.ofNullable(searchParams.getUids().split(",")).ifPresent(v -> {
            filters.add(boolFilter().must(termsFilter("uid", v)));
        });
        }
        //access for many categories
        if (searchParams.getCategories() != null) {
            for(String category : searchParams.getCategories().split(",")){
                 Optional.ofNullable(searchParams.getCategories().split(",")).ifPresent(v -> {
            filters.add(boolFilter().must(termsFilter("cat", v)));
        });
             }
        }

        if (searchParams.getItemId() != null) {
            boolQueryBuilder.must(queryStringQuery(searchParams.getItemId()).field("_id"));
        }

        if (Optional.ofNullable(searchParams.getTitle()).isPresent()) {
            boolQueryBuilder.must(queryStringQuery(searchParams.getTitle()).analyzeWildcard(true).field("title"));
        }

        if (Optional.ofNullable(searchParams.getStartDateFrom()).isPresent()
                || Optional.ofNullable(searchParams.getStartDateTo()).isPresent()) {
            filters.add(rangeFilter("start_date").from(searchParams.getStartDateFrom()).to(searchParams.getStartDateTo()));
        }

        if (Optional.ofNullable(searchParams.getEndDateFrom()).isPresent()
                || Optional.ofNullable(searchParams.getEndDateTo()).isPresent()) {
            filters.add(rangeFilter("end_date").from(searchParams.getEndDateFrom()).to(searchParams.getEndDateTo()));
        }

        if (Optional.ofNullable(searchParams.getPriceFrom()).isPresent()
                || Optional.ofNullable(searchParams.getPriceTo()).isPresent()) {
            filters.add(rangeFilter("price").from(searchParams.getPriceFrom()).to(searchParams.getPriceTo()));
        }

        searchQuery.withQuery(boolQueryBuilder);

        FilterBuilder[] filterArr = new FilterBuilder[filters.size()];
        filterArr = filters.toArray(filterArr);
        searchQuery.withFilter(andFilter(filterArr));

        if (searchParams.getOrderBy() != null && searchParams.getOrderDir() != null) {
            if (searchParams.getOrderDir().toLowerCase().equals("asc")) {
                searchQuery.withSort(SortBuilders.fieldSort(searchParams.getOrderBy()).order(SortOrder.ASC));
            } else {
                searchQuery.withSort(SortBuilders.fieldSort(searchParams.getOrderBy()).order(SortOrder.DESC));
            }
        }

        if (pageable != null) {
            searchQuery.withPageable(pageable);
        }
        return searchQuery;
    }

搜索持续15秒。 16k记录。

我们正在寻找参数

?uids=1,2&title=xyz

搜索持续15秒。 800条记录

我们正在寻找以下参数:

?uids=1,2

我将代码更改为(查看boolQueryBuilder):

private NativeSearchQueryBuilder getSearchQuery(AuctionIndexSearchParams searchParams, Pageable pageable) {
        final List<FilterBuilder> filters = Lists.newArrayList();
        final NativeSearchQueryBuilder searchQuery = new NativeSearchQueryBuilder().withQuery(matchAllQuery());

        Optional.ofNullable(searchParams.getCategoryId()).ifPresent(v -> filters.add(boolFilter().must(termFilter("cat", v))));
        Optional.ofNullable(searchParams.getCurrency()).ifPresent(v -> filters.add(boolFilter().must(termFilter("curr", v))));
        Optional.ofNullable(searchParams.getTreeCategoryId()).ifPresent(v -> filters.add(boolFilter().must(termFilter("tcat", v))));
        Optional.ofNullable(searchParams.getUid()).ifPresent(v -> filters.add(boolFilter().must(termFilter("uid", v))));
        final BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();

        //access for many uids
        if (searchParams.getUids() != null) {
            for (String user : searchParams.getUids().split(",")) {
                boolQueryBuilder.should(queryStringQuery(user).field("uid"));
            }
        }
        //access for many categories
        if (searchParams.getCategories() != null) {
            for(String category : searchParams.getCategories().split(",")){
                 boolQueryBuilder.should(queryStringQuery(category).field("cat"));
             }
        }

        if (searchParams.getItemId() != null) {
            boolQueryBuilder.must(queryStringQuery(searchParams.getItemId()).field("_id"));
        }

        if (Optional.ofNullable(searchParams.getTitle()).isPresent()) {
            boolQueryBuilder.must(queryStringQuery(searchParams.getTitle()).analyzeWildcard(true).field("title"));
        }

        if (Optional.ofNullable(searchParams.getStartDateFrom()).isPresent()
                || Optional.ofNullable(searchParams.getStartDateTo()).isPresent()) {
            filters.add(rangeFilter("start_date").from(searchParams.getStartDateFrom()).to(searchParams.getStartDateTo()));
        }

        if (Optional.ofNullable(searchParams.getEndDateFrom()).isPresent()
                || Optional.ofNullable(searchParams.getEndDateTo()).isPresent()) {
            filters.add(rangeFilter("end_date").from(searchParams.getEndDateFrom()).to(searchParams.getEndDateTo()));
        }

        if (Optional.ofNullable(searchParams.getPriceFrom()).isPresent()
                || Optional.ofNullable(searchParams.getPriceTo()).isPresent()) {
            filters.add(rangeFilter("price").from(searchParams.getPriceFrom()).to(searchParams.getPriceTo()));
        }

        searchQuery.withQuery(boolQueryBuilder);

        FilterBuilder[] filterArr = new FilterBuilder[filters.size()];
        filterArr = filters.toArray(filterArr);
        searchQuery.withFilter(andFilter(filterArr));

        if (searchParams.getOrderBy() != null && searchParams.getOrderDir() != null) {
            if (searchParams.getOrderDir().toLowerCase().equals("asc")) {
                searchQuery.withSort(SortBuilders.fieldSort(searchParams.getOrderBy()).order(SortOrder.ASC));
            } else {
                searchQuery.withSort(SortBuilders.fieldSort(searchParams.getOrderBy()).order(SortOrder.DESC));
            }
        }

        if (pageable != null) {
            searchQuery.withPageable(pageable);
        }
        return searchQuery;
    }

搜索持续3s。 16k记录。

我们正在寻找以下参数:

?uids=1,2&title=xyz

搜索持续3s。 300万条记录。

看起来好像查询这些参数是使用OR组合并返回太多结果。如何更改代码以找到工作 boolQueryBuilder

对于任何帮助,我将非常感激!

1 个答案:

答案 0 :(得分:1)

ElasticSearch的bool查询的工作方式是:

  • must查询必须与找到的文档匹配
  • should查询只会提高得分

如果must匹配,但should个查询都不匹配,则仍会返回must的所有结果。

请参阅https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-bool-query.html

根据您的实际搜索需求,您可能希望将查询包装在另一个uid中的titleand查询中 - 查询:https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-and-query.html

然后你会有这样的层次结构:

{
    "bool": {
         "must": {
             "and": [
                  "query_string": { /* for title */ },
                  "query_string": { /* for uid */ }
             ]
         },
         "should": [ /* more queries to boost documents with matching fields */ ]
    }

}

一般来说,我也会质疑使用search query - 查询uid。我想term查询可能会更高效。