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;

    }

좋은 웹페이지 즐겨찾기