欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

elasticsearch系列-Java客户端的查询操作

程序员文章站 2022-07-01 16:04:24
...

在上一篇中,我们介绍了如何使用Java客户端对elasticsearch进行索引的创建、mapping信息的设置和文档的添加,在本篇中我们将主要介绍通过Java客户端查询文档的操作。

使用Java客户端查询操作步骤

  • 创建一个client对象
  • 创建一个查询对象,通过QueryBuilders进行创建,其由很多实现的子类。
  • 使用client执行查询操作,需提前设置查询参数
  • 得到查询返回的结果,默认返回十条数据(如果返回条数过多,可能会导致内存溢出)。通过返回接口可以取查询结果的记录数,去查询结果列表等信息。
  • 关闭client对象。

根据ID查询文档

通过前面的学习,我们知道在添加文档时,elasticsearch会持有一个主键即"_id"。在查询时可以通过这个主键进行查询,示例demo如下所示。

    @Test
    public void queryById() throws UnknownHostException {
        ElasticSearchParams elasticSearchParams = new ElasticSearchParams();
        elasticSearchParams.setIndexName("20200128-xinghaol")
                .setIp("47.107.90.36")
                .setClusterName("my-elasticsearch")
                .setPort(9300);
        SearchResponse searchResponse = ElasticSearchUtil.queryById(elasticSearchParams);
        SearchHits searchHits = searchResponse.getHits();
        System.out.println("总数:" + searchHits.getTotalHits());
        SearchHit[] hits = searchHits.getHits();
        for (int i = 0; i < hits.length; i++) {
            SearchHit searchHit = hits[i];
            System.out.println("查询结果为:" + (i + 1) + " " + searchHit.getSourceAsString());
        }
    }

    public static SearchResponse queryById(ElasticSearchParams elasticSearchParams) throws UnknownHostException {
        TransportClient transportClient = buildTransportClient(elasticSearchParams);
        // 需要加判空
        // 查询id为1的记录
        QueryBuilder queryBuilder = QueryBuilders.idsQuery().addIds("1");
        SearchResponse searchResponse = transportClient.prepareSearch(elasticSearchParams.getIndexName())
                .setTypes(elasticSearchParams.getDocumentTypes())
                .setQuery(queryBuilder)
                .get();

        return searchResponse;
    }

    private static TransportClient buildTransportClient(ElasticSearchParams elasticSearchParams) throws UnknownHostException {
        if (Objects.isNull(elasticSearchParams) || Strings.isNullOrEmpty(elasticSearchParams.getIndexName())
                || Strings.isNullOrEmpty(elasticSearchParams.getIp())
                || Objects.isNull(elasticSearchParams.getPort())
                || Strings.isNullOrEmpty(elasticSearchParams.getClusterName())
                || elasticSearchParams.getPort() <= 0) {
            log.error("参数不合法");
            return null;
        }
        // 创建Settings
        Settings settings = Settings.builder()
                .put("cluster.name", elasticSearchParams.getClusterName())
                .put("client.transport.ignore_cluster_name", true)
                .build();

        // 创建transportclient对象
        TransportClient transportClient = new PreBuiltTransportClient(settings);
        transportClient.addTransportAddress(new TransportAddress(InetAddress.getByName(elasticSearchParams.getIp()), elasticSearchParams.getPort()));

        return transportClient;
    }

在SearchResponse对象中可以得到查询结果的各种信息,比如文档总条数、文档内容等。

根据Term方式查询

根据Trem方式查询与根据ID查询唯一的区别点在于在创建QueryBuilder时为termQuery(name,value)形式的实现方式,如下所示。

QueryBuilder queryBuilder = QueryBuilders.termQuery(elasticSearchParams.getTermQueryName(), elasticSearchParams.getTermQueryValue());

在得到SearchResponse后,与根据ID查询的后续操作相同,这里不再赘述。

根据QueryString查询

在前面介绍elasticsearch查询方式时,elasticsearch支持根据字符串的查询,Java客户端同样支持根据字符串的查询。在创建QueryBuilder时选择queryStringQuery()的实现方式,可以指定默认的搜索域,若不指定搜索域则在所有的与进行查询操作,其他操作不在赘述。

查询elasticsearch分页设置

在上面的查询操作中,我们介绍了elasticsearch默认是返回10条查询数据,但是如果我们想要查询更多或者分页查询操作该怎么办?在Java客户端中transprotClient查询之前设置起始行号和每页显示的条数,示例如下。

 transportClient.prepareSearch(elasticSearchParams.getIndexName())
                    .setTypes(elasticSearchParams.getDocumentTypes())
                    .setFrom(elasticSearchParams.getFrom())
                    .setSize(elasticSearchParams.getSize())
                    .setQuery(queryBuilder);

在查询结果中高亮显示

在使用百度、Google等搜索引擎时,查询出的结果都高亮显示了我们搜索的关键字,在elasticsearch中同样支持高亮的设置。在查询时需要指定一个高亮显示的字段,并且需要指定高亮显示的前缀和后缀,并将这些设置到client中,查询得到结果后可以查看高亮显示的结果。

使用HighlightBuilder设置要高亮的字段名称,以及要添加的前缀、后缀名称。在查询之前设置HighlightBuilder到transportClient中,实例代码如下所示。

    @Test
    public void queryHighLighter() throws UnknownHostException {
        ElasticSearchParams elasticSearchParams = new ElasticSearchParams();
        elasticSearchParams.setIndexName("20200126-xinghaol")
                .setIp("47.107.90.36")
                .setClusterName("my-elasticsearch")
                .setPort(9300);
        TransportClient transportClient = ElasticSearchUtil.obtainTransport(elasticSearchParams);
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("house_name");
        highlightBuilder.preTags("<em>");
        highlightBuilder.postTags("</em>");

        QueryBuilder queryBuilder = QueryBuilders.queryStringQuery("小屋").defaultField("house_name");

        SearchResponse searchResponse = transportClient.prepareSearch().
                setQuery(queryBuilder).
                highlighter(highlightBuilder).get();

        SearchHits searchHits = searchResponse.getHits();
        SearchHit[] hits = searchHits.getHits();
        for (int i = 0; i < hits.length; i++) {
            SearchHit searchHit = hits[i];
            Map<String, HighlightField> highlightFields = searchHit.getHighlightFields();
            HighlightField highlightField = highlightFields.get("house_name");
            Text[] fragments = highlightField.getFragments();
            if (fragments != null) {
                System.out.println("当前是第" + i + "个文档,文档内容:" + fragments[0].toString());
            }
        }
    }

运行上面demo示例得到如下结果,可以看到分词后的都已经加上了<em>标签,即完成了高亮显示的要求。

当前是第0个文档,文档内容:<em>小</em>数点价格房<em>屋</em>01
当前是第1个文档,文档内容:龙卷风<em>小屋</em>
当前是第2个文档,文档内容:爱的<em>小屋</em>
当前是第3个文档,文档内容:这是我修改的房<em>屋</em>名称
当前是第4个文档,文档内容:闪订房<em>屋</em>20200119

小节

在本篇中我们通过Java客户端完成了根据ID、关键词、字符串的查询方式,还介绍了elasticsearch中的分页设置及高亮显示的查询。希望对初学者有所帮助。