美文网首页
Elasticsearch 使用 Java High Level

Elasticsearch 使用 Java High Level

作者: SheHuan | 来源:发表于2020-12-15 21:49 被阅读0次

    上一篇我们学习了如何使用 Java High Level REST Client 的相关 API 来操作索引、文档,在此基础上,今天我们来学习如何文档查询。如果你之前已经掌握了如何使用 RESTful API 来实现文档查询,那么使用 Java High Level REST Client 相关的 API 进行文档查询时,你会发现似曾相似,简直就是一个模式,下边我们具体来看。

    1、QueryBuilders

    我们先认识一个类QueryBuilders,它提供了许多构建文档查询条件的静态方法,例如:

    public static MatchQueryBuilder matchQuery(String name, Object text) {}
    
    public static MatchPhraseQueryBuilder matchPhraseQuery(String name, Object text) {}
    
    public static TermQueryBuilder termQuery(String name, String value) {}
    
    public static RangeQueryBuilder rangeQuery(String name) {}
    
    public static BoolQueryBuilder boolQuery() {}
    ......
    ......
    

    可以看到这些静态方法都返回了一个 Builder 类型,其实我们也可以自己new对应的 Builder 类,QueryBuilders的相关静态方法就是这么做的,只是简化了我们的操作。通过这些 Builder 类就可以来构建我们的查询条件了,单从它们的名字来看就和我们之前学习 RESTful API 时的matchmatch_phrasetermrangebool很类似,其实就是一回事。

    例如,查询school北大,并且age大于等于10小于等于50的数据,可以使用如下方式构建查询条件:

    BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
            .must(new TermQueryBuilder("school.keyword", "北大"))
            .must(new RangeQueryBuilder("age").gte(10).lte(50));
    

    2、SearchSourceBuilder

    前边我们已经可以构建查询条件了,那么接下来就是如何去接收已有的查询条件了。这里需要使用SearchSourceBuilder类了:

    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    ...省略boolQueryBuilder的构建...
    searchSourceBuilder.query(boolQueryBuilder);
    

    SearchSourceBuilderquery方法用来接收一个查询条件的对象。SearchSourceBuilder除了接收查询条件,还可以对查询结果排序、分页、查询结果包含文档的那些字段、超时、高亮等等,下边我们来看几个常用的功能:

    • 排序
      按照age降序排列查询结果:
    searchSourceBuilder.sort("age", SortOrder.DESC);
    
    • 分页
      从第0行开始查询20条数据:
    searchSourceBuilder.from(0);
    searchSourceBuilder.size(20);
    
    • 字段过滤
      只返回文档中nameageschool三个字段:
    String[] includeFields = new String[]{"name", "age", "school"};
    searchSourceBuilder.fetchSource(includeFields, new String[]{});
    
    • 高亮
      设置高亮的字段以及高亮包裹的 html 标签:
    HighlightBuilder highlightBuilder = new HighlightBuilder()
            .field("name")
            .preTags("<span style='color:red'>")
            .postTags("</span>");
    searchSourceBuilder.highlighter(highlightBuilder);
    
    • 超时时间
      设置查询的超时时间为10秒:
    searchSourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS));
    

    3、SearchRequest

    通过QueryBuildersSearchSourceBuilder类,我们已经可以构建出复杂的查询了,接下就是去查询了:

    SearchRequest request = new SearchRequest("user");
    SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
    ...省略查询的构建过程...
    request.source(searchSourceBuilder);
    SearchResponse response = client.search(request, RequestOptions.DEFAULT);
    

    4、实例

    在编写实例之前,先根据上一篇的内容准备好如下数据:


    数据有了,就开始我们的查询吧。下边的查询代码基本用到了我们上边介绍的内容,关键的都有注释:

    public void searchDocument() throws IOException {
        SearchRequest request = new SearchRequest("user");
        SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder();
        // school 是清华或北大的
        BoolQueryBuilder schoolQueryBuilder = QueryBuilders.boolQuery()
                .should(QueryBuilders.termQuery("school.keyword", "北大"))
                // .should(QueryBuilders.matchPhraseQuery("school", "北大"))
                .should(QueryBuilders.termQuery("school.keyword", "清华"));
    
        BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery()
                .must(schoolQueryBuilder)
                // name 以王开头的
                .must(QueryBuilders.matchPhrasePrefixQuery("name", "王"))
                // age 大于等于10小于等于70
                .must(QueryBuilders.rangeQuery("age").gte(10).lte(70));
    
        // 设置查询条件
        searchSourceBuilder.query(boolQueryBuilder);
        // 字段过滤
        String[] includeFields = new String[]{"name", "age", "school"};
        searchSourceBuilder.fetchSource(includeFields, new String[]{});
        // 设置高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder()
                .field("name")
                .preTags("<span style='color:red'>")
                .postTags("</span>");
        searchSourceBuilder.highlighter(highlightBuilder);
        // 排序
        searchSourceBuilder.sort("age", SortOrder.DESC);
        // 分页
        searchSourceBuilder.from(0);
        searchSourceBuilder.size(20);
        // 超时时间
        searchSourceBuilder.timeout(new TimeValue(10, TimeUnit.SECONDS));
        request.source(searchSourceBuilder);
        // 发起查询请求
        SearchResponse response = client.search(request, RequestOptions.DEFAULT);
        for (SearchHit hit : response.getHits()) {
            // 提取高亮的字段内容,因为查询出来的文档数据和高亮字段的数据是分开的
            String highlightName = hit.getHighlightFields().get("name").fragments()[0].toString();
            // 提取查询出的文档数据,并转成对象
            User user = JSONObject.parseObject(hit.getSourceAsString(), User.class);
            // 用高亮的字段内容覆盖覆盖原文档字段
            user.setName(highlightName);
            System.out.println(JSON.toJSONString(user));
        }
    }
    

    查询结果如下:


    上边分页时每次的开始数据行数是一个固定值0,并不能真正的分页,要分页我们就要先通过总数据条数计算出总页数,总数数据条数可通过如下方法获得:

    long totalHits = response.getHits().getTotalHits().value;
    

    接下来具体的分页操作就简单了。

    关于文档的查询就先介绍这么多了,下一篇介绍文档的聚合查询。

    相关文章

      网友评论

          本文标题:Elasticsearch 使用 Java High Level

          本文链接:https://www.haomeiwen.com/subject/ndygwktx.html