ElasticSearch批量查询JavaApi实现

ElasticSearch 版本 6.8

背景

Elasticsearch 允许通过一次查询请求执行多个文档的检索,虽然 Elasticsearch 内部还是一条一条去检索,但是这样可以避免多次请求造成的单独网络开销,相对于一个一个的检索,这样的效率更高。
之前项目处理是一条一条去检索,后来改造为批处理后,单处理差不多优化了10s的效率左右,测试数据量大概在2w左右

java实现

es官方文档

相比单处理,我们批处理肯定是要先获取 单个 SearchRequest, 然后再装入一个请求中类似list中,然后发一次请求

获取单个请求

public SearchRequest getQuery(Drug drug, Boolean specFlag) {

        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();


        BoolQueryBuilder builder = QueryBuilders.boolQuery();
        BoolQueryBuilder nameMatch = QueryBuilders.boolQuery().minimumShouldMatch(1)
                .should(QueryBuilders.matchQuery("drugName",drug.getDrugName()))
                .should(QueryBuilders.matchQuery("productName",drug.getDrugName()));



        BoolQueryBuilder must = QueryBuilders.boolQuery().minimumShouldMatch(2)
                .should(nameMatch)
                .should(QueryBuilders.matchQuery("companyName", drug.getCompany()))
                .should(QueryBuilders.matchQuery("approvalIndex", drug.getApproval()));

        builder.must(must);
        if (specFlag) {
            BoolQueryBuilder specMatch = QueryBuilders.boolQuery().minimumShouldMatch(1)
                    .should(QueryBuilders.matchQuery("specIndex",drug.getSpec()))
                    .should(QueryBuilders.matchQuery("otherSpec",drug.getSpec()));
            builder.must(specMatch);
            builder.should(QueryBuilders.termQuery("specIndex.full", drug.getSpec()))
                    .should(QueryBuilders.termQuery("otherSpec.full", drug.getSpec()));

        }
        // 分页只要第一条查询结果
        searchSourceBuilder.query(builder).from(0).size(1);


        SearchRequest firstSearchRequest = new SearchRequest();
        firstSearchRequest.source(searchSourceBuilder);

        return firstSearchRequest;

    }

构造批处理请求

List<SearchRequest> searchRequests = Lists.newArrayListWithExpectedSize(sources.size());
// getQuery 为上面方法
SearchRequest query = clearSearch.getQuery(drug, false);
            searchRequests.add(query);

发送请求获取查询结果


@Autowired
ElasticsearchRestTemplate restTemplate;

 public List<DscStandardProduct> clearProduct(List<SearchRequest> searchRequests) {

        List<DscStandardProduct> products = new ArrayList<>();
        MultiSearchRequest request = new MultiSearchRequest();
        // 添加批量查询
        for (SearchRequest searchRequest : searchRequests) {
            request.add(searchRequest);
        }

        try {
            MultiSearchResponse multiResponse = restTemplate.getClient().msearch(request, RequestOptions.DEFAULT);
            for (MultiSearchResponse.Item item : multiResponse.getResponses()) {
                SearchHits hits = item.getResponse().getHits();

                if (CollectionUtil.isEmpty(hits)) {
                    products.add(null);
                    continue;
                }
                for (SearchHit hit : hits) {
                    String sourceAsString = hit.getSourceAsString();
                    DscStandardProduct product = JSONObject.parseObject(sourceAsString, DscStandardProduct.class);
                    products.add(product);
                }

            }

        } catch (IOException e) {
            e.printStackTrace();
        }

        return products;

    }

你可能感兴趣的:(ElasticSearch,elasticsearch,批量查询,批处理)