天天看点

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​​