1. 程式人生 > >elasticsearch 複合查詢

elasticsearch 複合查詢

                                                     ElasticSearch 複合查詢

 

1.pom依賴

<!-- https://mvnrepository.com/artifact/org.elasticsearch.client/transport -->
        <dependency>
            <groupId>org.elasticsearch.client</groupId>
            <artifactId>transport</artifactId>
        </dependency>

        <!-- elasticsearch -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.elasticsearch/elasticsearch -->
        <dependency>
            <groupId>org.elasticsearch</groupId>
            <artifactId>elasticsearch</artifactId>
        </dependency>

2.配置

spring:
    data:
        elasticsearch:
            cluster-name: senseguard-logging
            cluster-nodes: 172.20.25.89:31191
            properties:
                client.transport.sniff: true

3.配置類 config

@Configuration
public class EsConfig {
    private TransportClient client;

    @Value("${spring.data.elasticsearch.cluster-name}")
    private String clusterName;

    @Value("${spring.data.elasticsearch.cluster-nodes}")
    private String clusterAddress;

    @Bean
    public TransportClient esclient() {
        try {
            Settings settings = Settings.builder().put("cluster.name", clusterName).build();

            client = new PreBuiltTransportClient(settings);
            String[] nodes = clusterAddress.split(",");
            for (String node : nodes) {
                if (node.length() > 0) {
                    String[] hostPort = node.split(":");
                    this.client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName(hostPort[0]),
                            Integer.parseInt(hostPort[1])));
                }
            }
        } catch (Exception e) {
        }
        return client;
    }

}

4. TransportClient 複雜、混合、排序 查詢

/**
     * ES巢狀查詢最外層資料轉換成匯出資料.
     * 
     * @param source
     * @param export
     * @throws ParseException
     * @throws ExecutionException
     * @throws InterruptedException
     */
    public List<DetectHistory> search(ImdaRequest imda)
            throws ParseException, InterruptedException, ExecutionException {
        List<DetectHistory> detectHistorieList = new LinkedList<>();
        try {
            // 建立builder
            BoolQueryBuilder builder = QueryBuilders.boolQuery();

            // builder下有must、should以及mustNot 相當於sql中的and、or以及not
            Long startTime = imda.getCaptureTimeStart();
            Long endTime = imda.getCaptureTimeEnd();

            // 抓拍時間篩選
            builder.must(QueryBuilders.rangeQuery("capturedTime").gte(startTime).lte(endTime));

            // 攝像頭 ID
            if (imda.getCameraIds().size() > 0 && imda.getCameraIds().get(0) > 0) {
                builder.must(QueryBuilders.termsQuery("camera.id", imda.getCameraIds()));
            }
            // 人像庫
            if (imda.getFaceDatabase().size() > 0 && imda.getFaceDatabase().get(0) > 0) {
                builder.must(QueryBuilders.termsQuery("targetLibrary.id", imda.getFaceDatabase()));
            }

            // 確認時間篩
            RangeQueryBuilder confirmRangeQueryBuilder = QueryBuilders.rangeQuery("acknowledge.operationTime");
            // 挨個設定查詢條件,沒有就不加,如果是字串型別的,要加keyword字尾
            // 確認狀態
            if (!StringUtils.isEmpty(imda.getConfirmStatus()) && Integer.parseInt(imda.getConfirmStatus()) > 0) {
                if (!StringUtils.isEmpty(imda.getConfirmTimeStart())) {
                    Long confirmStart = imda.getConfirmTimeStart();
                    confirmRangeQueryBuilder.gte(confirmStart);
                }
                if (!StringUtils.isEmpty(imda.getConfirmTimeEnd())) {
                    Long confirmEnd = imda.getConfirmTimeEnd();
                    confirmRangeQueryBuilder.lte(confirmEnd);
                }
                builder.must(confirmRangeQueryBuilder);
                builder.must(QueryBuilders.matchPhraseQuery("acknowledge.status.keyword", imda.getConfirmStatus()));
            }

            BoolQueryBuilder keywordQueryShould = QueryBuilders.boolQuery();
            String keyword = imda.getName();
            // 搜尋關鍵字
            if (!StringUtils.isEmpty(keyword)) {
                String keywordLower = "*" + keyword.toLowerCase() + "*";
                keyword = "*" + keyword + "*";
                // 名字
                keywordQueryShould.should(QueryBuilders.wildcardQuery("target.lowerName.keyword", keywordLower));
                // 部門
                keywordQueryShould.should(QueryBuilders.wildcardQuery("target.lowerDept.keyword", keywordLower));
                //公司
                keywordQueryShould.should(QueryBuilders.wildcardQuery("target.lowerCompany.keyword", keywordLower));
                // camera name
                keywordQueryShould.should(QueryBuilders.wildcardQuery("camera.name.keyword", keyword));
                // keeper-group 名稱
                keywordQueryShould.should(QueryBuilders.wildcardQuery("camera.groupName.keyword", keyword));
                // 人像庫名稱
                keywordQueryShould.should(QueryBuilders.wildcardQuery("targetLibrary.name.keyword", keyword));
                // 員工編號
                keywordQueryShould.should(QueryBuilders.wildcardQuery("target.cardId.keyword", keyword));
                // 單位名稱
                keywordQueryShould.should(QueryBuilders.wildcardQuery("target.company.keyword", keyword));
                // 國籍
                keywordQueryShould.should(QueryBuilders.wildcardQuery("target.nationality.keyword", keyword));
                // 確認人的名稱
                keywordQueryShould.should(QueryBuilders.wildcardQuery("acknowledge.realname.keyword", keyword));
                // 確認人的id
//                keywordQueryShould.should(QueryBuilders.wildcardQuery("acknowledge.userId.keyword", keyword));
            }

            builder.must(keywordQueryShould);

            // 比對結果
            if (!StringUtils.isEmpty(imda.getComparedType()) && imda.getComparedType().size() > 0) {
                List<String> types = imda.getComparedType();

                BoolQueryBuilder comparedBuilder = null;
                BoolQueryBuilder comparedShould = QueryBuilders.boolQuery();

                for (String type : types) {
                    switch (type) {
                    case "NORMAL":
                        comparedBuilder = QueryBuilders.boolQuery();
                        comparedBuilder.must(QueryBuilders.matchQuery("detectStatus.keyword",
                                ComparedTypeEnum.NORMAL.getDetectStatus()));
                        comparedBuilder
                                .must(QueryBuilders.matchQuery("status.keyword", ComparedTypeEnum.NORMAL.getStatus()));
                        comparedShould.should(comparedBuilder);
                        break;
                    case "ABNORMAL":
                        comparedBuilder = QueryBuilders.boolQuery();
                        comparedBuilder.must(QueryBuilders.matchQuery("detectStatus.keyword",
                                ComparedTypeEnum.ABNORMAL.getDetectStatus()));
                        comparedBuilder.must(
                                QueryBuilders.matchQuery("status.keyword", ComparedTypeEnum.ABNORMAL.getStatus()));
                        comparedShould.should(comparedBuilder);
                        break;
                    case "STRANGER":
                        comparedBuilder = QueryBuilders.boolQuery();
                        comparedBuilder.must(QueryBuilders.matchQuery("detectStatus.keyword",
                                ComparedTypeEnum.STRANGER.getDetectStatus()));
                        comparedBuilder.must(
                                QueryBuilders.matchQuery("status.keyword", ComparedTypeEnum.STRANGER.getStatus()));
                        comparedShould.should(comparedBuilder);
                        break;
                    }
                }

                builder.must(comparedShould);
            }

            SortBuilder sortBuilder = SortBuilders.fieldSort("capturedTime").order(SortOrder.DESC);

            int size = 0;
            int from = 0;

            if (imda.getFrom() == imda.getTo()) {
                size = 1;
            } else {
                size = imda.getTo() - imda.getFrom() + 1;
            }
            if (imda.getFrom() > SFUUMSConstant.ONE) {
                from = imda.getFrom() - 1;
            }

            SearchResponse searchResponse = client.prepareSearch("tdhistory").setTypes("tdhistory")
                    .setSearchType(SearchType.DFS_QUERY_THEN_FETCH).setQuery(builder).addSort(sortBuilder).setFrom(from)
                    .setSize(size).execute().get();

            SearchHits searchHits = searchResponse.getHits();

            logger.info("td Conditional query total :" + searchHits.getTotalHits());

            DetectHistory detectHistory = null;

            for (SearchHit searchHit : searchHits) {
                detectHistory = JSON.parseObject(searchHit.getSourceAsString(), DetectHistory.class);  

                detectHistorieList.add(detectHistory);
            }
            return detectHistorieList;
        } catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }

        return detectHistorieList;
    }
 

5.查詢完畢,輸出結果

總結:

1.查詢欄位名要和存的欄位一樣,不然查詢不到結果

2.String 型別的欄位後面要加keyword 

3.String 查詢用 QueryStringQueryBuilder,時間段查詢用 RangeQueryBuilder