Elasticsearch8.17一键安装及全新Client开箱体验

1,335 阅读4分钟

前言

最近在学习优化Elasticsearch中文搜索时发现它已经更新到了8.17版本了,并且推出了全新的JAVA Client,目前我们使用的还是7.X的版本,本着学习新技术的态度于是下载安装了全新的8.17版本,并且体验了一下全新的JAVA Client,短期内应该不会更新到8.17也不会替换原有的JAVA Client的,先记录一波,说不定后面会有用到的时候。

优化搜索文章:《如何让ElasticSearch完美实现数据库的Like查询》

Elasticsearch Java API Client

Elasticsearch的官方全新的Java API 客户端主要有以下几个特点:

  • 返回结果支持JAVA对象,之前查出结果还要手动转成需要的JAVA对象
  • API支持同步和异步版本,异步可以有效的增加建立索引的吞吐量
  • 使用构建器模式实现fluent链式编程
  • 使用对象映射无缝集成应用程序类,例如Jackson或任何 JSON-B 实现。

全新Java Client支持版本

安装

最简单方便的是使用Docker一键安装ElasticSearch+Kibana

curl -fsSL https://elastic.co/start-local | sh

脚本执行完成后会在控制台输出Kibana访问地址和对应的账号密码,打开后就安装完成了

脚本地址:github.com/elastic/sta…

安装IK分词器:

 docker exec -it  es-local-dev   /bin/bash 
 /usr/share/elasticsearch/bin/elasticsearch-plugin install https://get.infini.cloud/elasticsearch/analysis-ik/8.17.0

ElasticSearch对应的IK分词词版本:release.infinilabs.com/analysis-ik…

安装完成后进入Kibana 页面:

完成安装

全新的JAVA Client

引入依赖

目前最新的版本为8.17.0,内部使用jackson作JSON数据的反序列化,引用Jackson的版本为2.17.0

<dependency>
  <groupId>co.elastic.clients</groupId>
  <artifactId>elasticsearch-java</artifactId>
  <version>8.17.0</version>
</dependency>

<dependency>
  <groupId>com.fasterxml.jackson.core</groupId>
  <artifactId>jackson-databind</artifactId>
  <version>2.17.0</version>
</dependency>

创建Client

public static String serverUrl = "http://localhost:9200";
public static String apiKey = "TUJSSzhwTUJlOUNsckptS0poS***";

public static ElasticsearchClient esClient;
static {
    RestClient restClient = RestClient
            .builder(HttpHost.create(serverUrl))
            .setDefaultHeaders(new Header[]{
                    new BasicHeader("Authorization", "ApiKey " + apiKey)
            }).build();
    ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
    esClient = new ElasticsearchClient(transport);
}

创建ElasticsearchClient需要两个参数,一个是接口地址,另一个是认证ApiKey,其中ApiKey可以从Kibana后台Security-ApiKeys中创建

Kibana后台创建ApiKeys

新建测试索引

我们创建一个test索引

PUT /test
{
    "mappings": {
        "properties": {
            "title": {
                "type": "text",
                "analyzer": "ik_max_word"
            },
               "rank": {
                "type": "long"
            },
             "pubTime": {
                "type": "date",
                "format": "yyyy-MM-dd HH:mm:ss||yyyy-MM-dd||epoch_millis"
            }
        }
    }
}

并创建对应的JAVA对象

@Data
@NoArgsConstructor
@AllArgsConstructor
public class Doc {
    private Long rank;
    private Date pubTime;
    private String title;
}

索引添加单文档

可以看出全新的Client在添加文档时我们不需要将JAVA转成JSON数据了,直接传入Doc对象

@Test
public void testIndex() throws IOException {
    ElasticsearchClient esClient = ESClient.esClient;
    for(Doc doc:docs){
        IndexResponse response = esClient.index(j -> j
                .index(indexName)
                .id(doc.getId().toString())
                .document(doc)
        );
        log.info("index {}", response.result().jsonValue());
    }
}

索引批量添加文档

@Test
public void testBulkIndex() throws IOException {
    BulkRequest.Builder br = new BulkRequest.Builder();
    docs.forEach(doc->{
        br.operations(op -> op
                .index(idx -> idx
                        .index(indexName)
                        .id(doc.getId().toString())
                        .document(doc)
                )
        );
    });
    ElasticsearchClient esClient = ESClient.esClient;
    BulkResponse result = esClient.bulk(br.build());
    if (result.errors()) {
        log.error("Bulk had errors");
        for (BulkResponseItem item: result.items()) {
            if (item.error() != null) {
                log.error(item.error().reason());
            }
        }
    }
}

通过ID查询文档

@Test
public void testQueryById() throws IOException {
    ElasticsearchClient esClient = ESClient.esClient;
    //使用对象接收
    GetResponse<Doc> response = esClient.get(g -> g
                    .index(indexName)
                    .id("1"),
            Doc.class
    );
    if (response.found()) {
        Doc doc = response.source();
        log.info("title :{} " , doc.getTitle());
    } else {
        log.info ("doc not found");
    }

    //使用Jackson接收
    GetResponse<ObjectNode> responseJSON = esClient.get(g -> g
                    .index(indexName)
                    .id("1"),
            ObjectNode.class
    );
    if (response.found()) {
        ObjectNode json = responseJSON.source();
        String title = json.get("title").asText();
        log.info("title :{} " , title);
    } else {
        log.info ("doc not found");
    }
}

使用match搜索文档

@Test
public void testSearch() throws IOException {
    ElasticsearchClient esClient = ESClient.esClient;
    String keyWord = "中国";
    SearchResponse<Doc> response = esClient.search(s -> s
                    .index(indexName)
                    .query(q -> q
                            .match(t -> t
                                    .field("title")
                                    .query(keyWord)
                            )
                    ),
            Doc.class
    );
    List<Hit<Doc>> hits = response.hits().hits();
    hits.forEach(hit -> {
        Doc doc = hit.source();
        log.info("{} {} {} ", doc.getTitle(), DateUtil.formatDate(doc.getPubTime()) ,doc.getRank());
    });
}

聚合查询

@Test
public void testAggr() throws IOException {
    ElasticsearchClient esClient = ESClient.esClient;
    String keyWord = "中国";
    Query query = MatchQuery.of(m -> m
            .field("title")
            .query(keyWord)
    )._toQuery();

    SearchResponse<Void> response = esClient.search(b -> b
                    .index(indexName)
                    .size(0)
                    .query(query)
                    .aggregations("yearHistogram", a -> a.dateHistogram(h -> h.calendarInterval(CalendarInterval.Year).field("pubTime"))
                    ),
            Void.class
    );

    List<DateHistogramBucket> buckets = response.aggregations()
            .get("yearHistogram")
            .dateHistogram()
            .buckets().array();

    for (DateHistogramBucket bucket: buckets) {
        log.info("{} {}  ", bucket.keyAsString(),bucket.docCount());
    }
}

更多查询参数参考:www.elastic.co/guide/en/el…

总结

在本文中,我们探讨了Elasticsearch 8.17版本及其全新的Java API Client。新版本的Java Client具有多个显著特点,包括支持直接返回Java对象、提供同步和异步API、采用流式编程的构建器模式,以及与JSON-B实现的无缝集成。这些特性使得开发者在使用Elasticsearch时更加高效便捷。

我们还详细介绍了如何通过Docker快速安装Elasticsearch和Kibana,并安装IK分词器。接着,展示了如何引入依赖、创建Elasticsearch Client、以及如何进行索引的创建和文档的添加。通过示例代码,我们演示了如何通过ID查询文档、使用match进行搜索、以及进行聚合查询。

总的来说,Elasticsearch 8.17及其新的Java Client为开发者提供了更强大的功能和更简便的操作方式,值得在实际项目中进行尝试和应用。