java - 创建加速搜索查询elasticsearch

标签 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;
    }
<小时/>

搜索持续 3 秒。 16k 条记录。

我们正在寻找以下参数:

?uids=1,2&title=xyz

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

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

如果有任何帮助,我将非常感激!

最佳答案

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

  • 必须查询,嗯,必须与找到的文档匹配
  • should 查询只会提高结果分数

如果 must 匹配,但没有任何 should 查询匹配,则仍会返回 must 的所有结果。

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

根据您的实际搜索需求,您可能希望将 uidtitle 的查询包装在另一个 and 查询中: 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 */ ]
    }

}

一般来说,我还会质疑使用搜索查询 - uid 查询。我猜想 term 查询可能性能更高。

关于java - 创建加速搜索查询elasticsearch,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38011103/

相关文章:

java - 我的 tcp 客户端/服务器程序中没有写入任何值

java - Jframe 中图像不刷新

elasticsearch - 部分更新覆盖整个结构

elasticsearch - JanusGraph 的 ES 字段映射到 `geo_shape`

java - 我希望我的 spring boot 应用程序连接到 JNDI 数据源(服务器 :wildfly)

java - 如何从 dockerized spring boot 连接 dockerized couchbase 服务器

java - HttpClient 的多线程问题

ruby-on-rails - 用 bool block 过滤(轮胎/ Elasticsearch )

java - 在父 build.gradle 中找不到 ID 为 spring-boot 的插件

java - 字符串替换正则表达式