Elasticsearch 使用 Java High Level REST Client 查询文档

上一篇我们学习了如何使用 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;

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

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

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,616评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,020评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,078评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,040评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,154评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,265评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,298评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,072评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,491评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,795评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,970评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,654评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,272评论 3 318
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,985评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,223评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,815评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,852评论 2 351

推荐阅读更多精彩内容