天天看點

ElasticSearch Java API之進階查詢(分頁查詢,高亮查詢,正規表達式查詢,聚合查詢等)

ElasticSearch 封裝了很多查詢方法

首先我們需要批量插入資料,以做測試使用

static void batchInsertDocument(RestHighLevelClient client) throws IOException {
    //建立批量新增請求對象
    BulkRequest request = new BulkRequest();
    request.add(new
            IndexRequest().index("userxt")
                    .id("1").source(XContentType.JSON,"name","xt","age","24")
            );
    request.add(new
            IndexRequest().index("userxt")
                    .id("2").source(XContentType.JSON, "name", "java","age","67")
            );
    request.add(new
            IndexRequest().index("userxt")
                    .id("3").source(XContentType.JSON, "name", "python","age","31")
            );
    request.add(new
            IndexRequest().index("userxt")
                    .id("4").source(XContentType.JSON, "name", "go","age","12")
            );
    //用戶端發送請求,擷取響應對象
    BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
    //列印結果資訊
    System.out.println("took:" + responses.getTook());
    System.out.println("items:" + responses.getItems());
}      

查詢所有文檔資料

//查詢所有文檔資料
static void queryAllDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

    // 建構查詢的請求體
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    // 查詢所有資料
    sourceBuilder.query(QueryBuilders.matchAllQuery());
    //發送請求,獲得結果
    searchFunction(client,request,sourceBuilder);

}      

條件查詢

//條件查詢
static void conditionQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {
    // 建構查詢的請求體
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.query(QueryBuilders.termQuery("age", "24"));

    //發送請求,獲得結果
    searchFunction(client,request,sourceBuilder);
}      

分頁查詢

// 分頁查詢
static void pagingQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {
    // 建構查詢的請求體
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.query(QueryBuilders.matchAllQuery());
    // 分頁查詢
    // 目前頁其實索引(第一條資料的順序号), from
    sourceBuilder.from(0);

    // 每頁顯示多少條 size  預設為10
    sourceBuilder.size(2);

    //發送請求,獲得結果
    searchFunction(client,request,sourceBuilder);
}      

對查詢進行排序

// 對查詢進行排序
static void orderingQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

    // 建構查詢的請求體
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.query(QueryBuilders.matchAllQuery());
    // 排序
    sourceBuilder.sort("age", SortOrder.ASC);

    //發送請求,獲得結果
    searchFunction(client,request,sourceBuilder);
}      

bool查詢(組合多條件查詢)

// 組合多條件查詢
static void combinationQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

    // 建構查詢的請求體
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    // 必須包含
    boolQueryBuilder.must(QueryBuilders.matchQuery("age", "24"));
    // 一定不含
    boolQueryBuilder.mustNot(QueryBuilders.matchQuery("name", "go"));
    // 可能包含
    boolQueryBuilder.should(QueryBuilders.matchQuery("sex", "男"));
    sourceBuilder.query(boolQueryBuilder);
    
    //發送請求,獲得結果
    searchFunction(client,request,sourceBuilder);
}      

範圍查詢

//範圍查詢
static void rangeQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {
    // 建構查詢的請求體
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");
    // 大于等于  gt 大于
    rangeQuery.gte("20");
    // 小于等于 lt 小于
    rangeQuery.lte("50");
    sourceBuilder.query(rangeQuery);
    
    //發送請求,獲得結果
    searchFunction(client,request,sourceBuilder);
}      

模糊查詢

//模糊查詢  當使用者輸入有錯誤時,使用這個功能能在一定程度上召回一些和輸入相近的文檔。
static void fuzzyQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

    // 建構查詢的請求體
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //Damerau發現 80% 的人類拼寫錯誤的編輯距離都是1. 換句話說, 80% 的拼寫錯誤都可以通過 單次編輯修改為原始的字元串.
    sourceBuilder.query(QueryBuilders.fuzzyQuery("name","xt2").fuzziness(Fuzziness.ONE));
    //發送請求,獲得結果
    searchFunction(client,request,sourceBuilder);
}      

通配符查詢

//通配符查詢 支援* 任意字元串;?任意一個字元
 static void wildcardQueryDocuments(RestHighLevelClient client,SearchRequest request){
     // 建構查詢的請求體
     SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
     sourceBuilder.query(QueryBuilders.wildcardQuery("name","x*"));
     //發送請求,獲得結果
     try {
         searchFunction(client,request,sourceBuilder);
     } catch (IOException e) {
         e.printStackTrace();
     }
 }      

正規表達式查詢

正規表達式規則:

  • ‘’."代表任意字元
  • "+"代表加号之前的最小單元比對一次或多次
  • "*"代表星号之前的最小單元比對零次或多次
  • "?"代表問号之前的最小單元比對零次或一次
  • "{}"可以被用來聲明之前的最小單元出現一個最少次數和最多次數 {2,5} 最少2次,最多5次
  • "()"被用來分組構成一個最小單元或者說是子模式 (ab)+ 代表ab比對一次或多次
  • "|"可以作為一個或的操作符,符号左右側的内容有一個比對上就認為是比對成功
  • "[]"作為一個選擇符,意思是中括号内的任意字元出現都認為是比對成功,加上^代表相反的意思,也就是說後的任意字元不出現都認為是比對成功。
//正規表達式查詢
static void regexpQueryDocuments(RestHighLevelClient client,SearchRequest request){
    // 建構查詢的請求體
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //''."代表任意字元
    //"+"代表加号之前的最小單元比對一次或多次
    //"*"代表星号之前的最小單元比對零次或多次
    //"?"代表問号之前的最小單元比對零次或一次
    //"{}"可以被用來聲明之前的最小單元出現一個最少次數和最多次數 {2,5} 最少2次,最多5次
    //"()"被用來分組構成一個最小單元或者說是子模式  (ab)+ 代表ab比對一次或多次
    //"|"可以作為一個或的操作符,符号左右側的内容有一個比對上就認為是比對成功
    //"[]"作為一個選擇符,意思是中括号内的任意字元出現都認為是比對成功,加上^代表相反的意思,也就是說後的任意字元不出現都認為是比對成功。
    sourceBuilder.query(QueryBuilders.regexpQuery("name","x.*"));
    //發送請求,獲得結果
    try {
        searchFunction(client,request,sourceBuilder);
    } catch (IOException e) {
        e.printStackTrace();
    }
}      

高亮查詢

// 高亮查詢
static void highlightQueryDocuments(RestHighLevelClient client) throws IOException {
    SearchRequest request = new SearchRequest().indices("userxt");
    //2.建立查詢請求體建構器
    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    //建構查詢方式:高亮查詢
    TermsQueryBuilder termsQueryBuilder =
            QueryBuilders.termsQuery("name","xt");
    //設定查詢方式
    sourceBuilder.query(termsQueryBuilder);
    //建構高亮字段
    HighlightBuilder highlightBuilder = new HighlightBuilder();
    highlightBuilder.preTags("<font color='red'>");//設定标簽字首  可以自定義  預設為em 标簽對
    highlightBuilder.postTags("</font>");//設定标簽字尾
    highlightBuilder.field("name");//設定高亮字段
    //設定高亮建構對象
    sourceBuilder.highlighter(highlightBuilder);
    //設定請求體
    request.source(sourceBuilder);
    //3.用戶端發送請求,擷取響應對象
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    //4.列印響應結果
    SearchHits hits = response.getHits();
    System.out.println("took:"+response.getTook());
    System.out.println("time_out:"+response.isTimedOut());
    System.out.println("total:"+hits.getTotalHits());
    System.out.println("max_score:"+hits.getMaxScore());
    System.out.println("--------------hits-------------");
    for (SearchHit hit : hits) {
        String sourceAsString = hit.getSourceAsString();
        System.out.println(sourceAsString);
        //列印高亮結果
        Map<String, HighlightField> highlightFields = hit.getHighlightFields();
        System.out.println(highlightFields);
    }
    System.out.println("--------------hits-------------");
}      

聚合查詢

//聚合查詢
static void aggregateQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

    SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
    sourceBuilder.aggregation(
            // 裡面封裝了很多 其他操作,可以自己修改
            AggregationBuilders.terms("age_groupby").field("age")
    );

    //發送請求,獲得結果
    searchFunction(client,request,sourceBuilder);

}      

如下圖所示,封裝了很多操作

完整代碼

public class AdvancedOperation {

    public static void main(String[] args) throws IOException {

        final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
        credentialsProvider.setCredentials(AuthScope.ANY,
                new UsernamePasswordCredentials("xt", "xt"));


        RestClientBuilder restClientBuilder = RestClient.builder(
                new HttpHost("IP", 9200,"http"));

        // 認證和線程數
        restClientBuilder.setHttpClientConfigCallback(httpClientBuilder -> {
            httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider);
            int threadCount = 10;
            httpClientBuilder.setDefaultIOReactorConfig(IOReactorConfig.custom().setIoThreadCount(threadCount).build());

            return httpClientBuilder;
        });

        // 逾時逾時設定
        restClientBuilder.setRequestConfigCallback(requestConfigCallback -> {
            requestConfigCallback.setConnectTimeout(10000); //機關ms
            requestConfigCallback.setSocketTimeout(10000);
            return requestConfigCallback;
        });


        // 建立用戶端對象   雖然已經被棄用,但是了解基本使用還是沒有問題  裡面封裝了RestClient
        RestHighLevelClient client = new RestHighLevelClient(restClientBuilder);

        System.out.println(client);



        //批量插入資料
//        batchInsertDocument(client);


        // 建立搜尋請求對象
        SearchRequest request = new SearchRequest();
        request.indices("userxt");


        //查詢所有文檔資料
        queryAllDocuments(client,request);
        //條件查詢
        conditionQueryDocuments(client,request);
        //分頁查詢
        pagingQueryDocuments(client,request);
        // 對查詢進行排序
        orderingQueryDocuments(client,request);
        // 組合多條件查詢
        combinationQueryDocuments(client,request);
        //範圍查詢
        rangeQueryDocuments(client,request);
        //模糊查詢
        fuzzyQueryDocuments(client,request);
        //通配符查詢
        wildcardQueryDocuments(client,request);

        //正規表達式查詢
        regexpQueryDocuments(client,request);

        //高亮查詢
        highlightQueryDocuments(client,request);

        //聚合查詢,有多種操作,min,max,avg,分組查詢等等
        aggregateQueryDocuments(client,request);
    }


    static void batchInsertDocument(RestHighLevelClient client) throws IOException {
        //建立批量新增請求對象
        BulkRequest request = new BulkRequest();
        request.add(new
                IndexRequest().index("userxt")
                        .id("1").source(XContentType.JSON,"name","xt","age","24")
                );
        request.add(new
                IndexRequest().index("userxt")
                        .id("2").source(XContentType.JSON, "name", "java","age","67")
                );
        request.add(new
                IndexRequest().index("userxt")
                        .id("3").source(XContentType.JSON, "name", "python","age","31")
                );
        request.add(new
                IndexRequest().index("userxt")
                        .id("4").source(XContentType.JSON, "name", "go","age","12")
                );
        //用戶端發送請求,擷取響應對象
        BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
        //列印結果資訊
        System.out.println("took:" + responses.getTook());
        System.out.println("items:" + responses.getItems());
    }



    //查詢所有文檔資料
    static void queryAllDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        // 查詢所有資料
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        //發送請求,獲得結果
        searchFunction(client,request,sourceBuilder);

    }

    //條件查詢
    static void conditionQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {
        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.termQuery("age", "24"));

        //發送請求,獲得結果
        searchFunction(client,request,sourceBuilder);
    }

    // 分頁查詢
    static void pagingQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {
        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        // 分頁查詢
        // 目前頁其實索引(第一條資料的順序号), from
        sourceBuilder.from(0);

        // 每頁顯示多少條 size  預設為10
        sourceBuilder.size(2);

        //發送請求,獲得結果
        searchFunction(client,request,sourceBuilder);
    }

    // 對查詢進行排序
    static void orderingQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.matchAllQuery());
        // 排序
        sourceBuilder.sort("age", SortOrder.ASC);

        //發送請求,獲得結果
        searchFunction(client,request,sourceBuilder);
    }

    // 組合多條件查詢
    static void combinationQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
        // 必須包含
        boolQueryBuilder.must(QueryBuilders.matchQuery("age", "24"));
        // 一定不含
        boolQueryBuilder.mustNot(QueryBuilders.matchQuery("name", "go"));
        // 可能包含
        boolQueryBuilder.should(QueryBuilders.matchQuery("sex", "男"));
        sourceBuilder.query(boolQueryBuilder);

        //發送請求,獲得結果
        searchFunction(client,request,sourceBuilder);
    }

    //範圍查詢
    static void rangeQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {
        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");
        // 大于等于  gt 大于
        rangeQuery.gte("20");
        // 小于等于 lt 小于
        rangeQuery.lte("50");
        sourceBuilder.query(rangeQuery);

        //發送請求,獲得結果
        searchFunction(client,request,sourceBuilder);
    }

    //模糊查詢  當使用者輸入有錯誤時,使用這個功能能在一定程度上召回一些和輸入相近的文檔。
    static void fuzzyQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //Damerau發現 80% 的人類拼寫錯誤的編輯距離都是1. 換句話說, 80% 的拼寫錯誤都可以通過 單次編輯修改為原始的字元串.
        sourceBuilder.query(QueryBuilders.fuzzyQuery("name","xt2").fuzziness(Fuzziness.ONE));
        //發送請求,獲得結果
        searchFunction(client,request,sourceBuilder);
    }

    //通配符查詢 支援* 任意字元串;?任意一個字元
    static void wildcardQueryDocuments(RestHighLevelClient client,SearchRequest request){
        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.query(QueryBuilders.wildcardQuery("name","x*"));
        //發送請求,獲得結果
        try {
            searchFunction(client,request,sourceBuilder);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    //正規表達式查詢
    static void regexpQueryDocuments(RestHighLevelClient client,SearchRequest request){
        // 建構查詢的請求體
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //''."代表任意字元
        //"+"代表加号之前的最小單元比對一次或多次
        //"*"代表星号之前的最小單元比對零次或多次
        //"?"代表問号之前的最小單元比對零次或一次
        //"{}"可以被用來聲明之前的最小單元出現一個最少次數和最多次數 {2,5} 最少2次,最多5次
        //"()"被用來分組構成一個最小單元或者說是子模式  (ab)+ 代表ab比對一次或多次
        //"|"可以作為一個或的操作符,符号左右側的内容有一個比對上就認為是比對成功
        //"[]"作為一個選擇符,意思是中括号内的任意字元出現都認為是比對成功,加上^代表相反的意思,也就是說後的任意字元不出現都認為是比對成功。
        sourceBuilder.query(QueryBuilders.regexpQuery("name","x.*"));
        //發送請求,獲得結果
        try {
            searchFunction(client,request,sourceBuilder);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    // 高亮查詢
    static void highlightQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

        //2.建立查詢請求體建構器
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        //建構查詢方式:高亮查詢
        TermsQueryBuilder termsQueryBuilder =
                QueryBuilders.termsQuery("name","xt");
        //設定查詢方式
        sourceBuilder.query(termsQueryBuilder);
        //建構高亮字段
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.preTags("<font color='red'>");//設定标簽字首  可以自定義  預設為em 标簽對
        highlightBuilder.postTags("</font>");//設定标簽字尾
        highlightBuilder.field("name");//設定高亮字段
        //設定高亮建構對象
        sourceBuilder.highlighter(highlightBuilder);


        //設定請求體
        request.source(sourceBuilder);
        //3.用戶端發送請求,擷取響應對象
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        //4.列印響應結果
        SearchHits hits = response.getHits();
        System.out.println("took:"+response.getTook());
        System.out.println("time_out:"+response.isTimedOut());
        System.out.println("total:"+hits.getTotalHits());
        System.out.println("max_score:"+hits.getMaxScore());
        System.out.println("--------------hits-------------");
        for (SearchHit hit : hits) {
            String sourceAsString = hit.getSourceAsString();
            System.out.println(sourceAsString);
            //列印高亮結果
            Map<String, HighlightField> highlightFields = hit.getHighlightFields();
            System.out.println(highlightFields);
        }
        System.out.println("--------------hits-------------");
    }

    //聚合查詢
    static void aggregateQueryDocuments(RestHighLevelClient client,SearchRequest request) throws IOException {

        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
        sourceBuilder.aggregation(
                // 裡面封裝了很多 其他操作,可以自己修改
                AggregationBuilders.terms("age_groupby").field("age")
        );

        //發送請求,獲得結果
        searchFunction(client,request,sourceBuilder);

    }



    private static void searchFunction(RestHighLevelClient client,SearchRequest request,SearchSourceBuilder sourceBuilder) throws IOException {
        //設定請求體
        request.source(sourceBuilder);
        //用戶端發送請求,擷取響應對象
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        // 列印響應結果
        SearchHits hits = response.getHits();
        System.out.println("took:" + response.getTook());
        System.out.println("timeout:" + response.isTimedOut());
        System.out.println("total:" + hits.getTotalHits());
        System.out.println("MaxScore:" + hits.getMaxScore());
        System.out.println("--------------hits-------------");
        for (SearchHit hit : hits) {
            //輸出每條查詢的結果資訊
            System.out.println(hit.getSourceAsString());
        }
        System.out.println("---------------hits-------------");
    }
}      

References:

  • ​​https://www.jianshu.com/p/a85b60e86d7b​​
  • ​​https://www.bilibili.com/video/BV1hh411D7sb?p=25​​
  • ​​https://www.jianshu.com/p/c2767e980368​​