Elasticsearch 是一个分布式的、面向生产规模工作负载优化的搜索引擎。
Kibana 可以将 Elasticsearch 中的数据转化为直观的图表、图形和仪表盘。
这篇文章,您将学习本地安装 Elasticsearch 和 Kibana,以及使用开发工具/ Java SDK 创建索引和搜索数据。
1 本地安装 {#1-%E6%9C%AC%E5%9C%B0%E5%AE%89%E8%A3%85}
1.1 创建网络 {#1.1-%E5%88%9B%E5%BB%BA%E7%BD%91%E7%BB%9C}
我们需要创建一个供 Elasticsearch 和 Kibana 使用的 network。这个 network 将被用于 Elasticsearch 和 Kibana 之间的通信。
docker network create elastic
1.2 安装 ES {#1.2-%E5%AE%89%E8%A3%85-es}
拉取 Elasticsearch 镜像
docker pull docker.elastic.co/elasticsearch/elasticsearch:{version}
这里的版本 version
,我们选取:8.9.0
。
docker pull docker.elastic.co/elasticsearch/elasticsearch:8.9.0
启动 docker elasticsearch 镜像
docker run --name elasticsearch --net elastic -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" -t docker.elastic.co/elasticsearch/elasticsearch:8.9.0
进入ES容器,修改 elasticsearch 用户密码
bin/elasticsearch-reset-password --username elastic -i
1.3 安装 Kibana {#1.3-%E5%AE%89%E8%A3%85-kibana}
拉取 Kibana 镜像
docker pull docker.elastic.co/kibana/kibana:8.9.0
启动 Kibana 镜像
docker run --name kibana --net elastic -p 5601:5601 docker.elastic.co/kibana/kibana:8.9.0
因为启动安装 Kibana ,需要 token , 所以进入 elasticsearch 容器 ,执行:
bin/elasticsearch-create-enrollment-token -s kibana
输入 token 之后,刷新页面,进入登录页面:
2 接口测试 {#2-%E6%8E%A5%E5%8F%A3%E6%B5%8B%E8%AF%95}
我们可以使用 Kibana Dev tools 来进行接口测试。
2.1 添加 {#2.1-%E6%B7%BB%E5%8A%A0}
向索引添加单个文档,提交一个 HTTP POST 请求,目标是该索引。
POST /customer/_doc/1
{
"firstname": "Jennifer",
"lastname": "Walters"
}
该请求会自动创建名为customer
的索引(如果不存在),然后添加一个 ID 为 1的新文档,同时存储并建立firstname
和lastname
字段的索引。
新文档可以立即从集群中的任何节点获取。您可以使用 GET 请求来检索它,请求中需指定其文档 ID :
GET /customer/_doc/1
要一次性添加多个文档,请使用 _bulk API。批量数据必须是以换行分隔的 JSON(NDJSON)格式。每一行必须以换行字符(\n)结尾,包括最后一行。
PUT customer/_bulk
{ "create": { } }
{ "firstname": "Monica","lastname":"Rambeau"}
{ "create": { } }
{ "firstname": "Carol","lastname":"Danvers"}
{ "create": { } }
{ "firstname": "Wanda","lastname":"Maximoff"}
{ "create": { } }
{ "firstname": "Jennifer","lastname":"Takeda"}
2.2 搜索 {#2.2-%E6%90%9C%E7%B4%A2}
已索引的文档可以在准实时的情况下进行搜索。下面的搜索将在customer索引中匹配所有名为 Jennifer 的顾客。
GET customer/_search
{
"query" : {
"match" : { "firstname": "Jennifer" }
}
}
2.3 视图 {#2.3-%E8%A7%86%E5%9B%BE}
进入 Kibana Data Views :
然后创建数据视图 :
创建数据视图之后,可以在 **Analytics > Discover ** 查看索引数据。
3 Java SDK 实战 {#3-java-sdk-%E5%AE%9E%E6%88%98}
3.1 依赖 {#3.1-%E4%BE%9D%E8%B5%96}
<dependency>
<groupId>co.elastic.clients</groupId>
<artifactId>elasticsearch-java</artifactId>
<version>8.9.0</version>
</dependency>
\<dependency\>
\<groupId\>io.github.hakky54\</groupId\>
\<artifactId\>sslcontext-kickstart\</artifactId\>
\<version\>7.1.0\</version\>
\</dependency\>
\<dependency\>
\<groupId\>com.fasterxml.jackson.core\</groupId\>
\<artifactId\>jackson-databind\</artifactId\>
\<version\>2.12.3\</version\>
\</dependency\>
\<dependency\>
\<groupId\>com.fasterxml.jackson.core\</groupId\>
\<artifactId\>jackson-core\</artifactId\>
\<version\>2.12.3\</version\>
\</dependency\>
\<dependency\>
\<groupId\>com.fasterxml.jackson.core\</groupId\>
\<artifactId\>jackson-annotations\</artifactId\>
\<version\>2.12.3\</version\>
\</dependency\>
\<dependency\>
\<groupId\>jakarta.json\</groupId\>
\<artifactId\>jakarta.json-api\</artifactId\>
\<version\>2.0.1\</version\>
\</dependency\>
`<!-- 强制走高版本 ,防止和springboot 依赖冲突 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-client</artifactId>
<version>8.9.0</version>
</dependency>
`
3.2 创建客户端 {#3.2-%E5%88%9B%E5%BB%BA%E5%AE%A2%E6%88%B7%E7%AB%AF}
1、通过用户名和密码创建客户端
RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200, "https"));
final CredentialsProvider credentialsProvider = new BasicCredentialsProvider();
credentialsProvider.setCredentials(AuthScope.ANY, new UsernamePasswordCredentials("elastic", "ilxw@19841201"));
// Elasticsearch 提供了 Https 服务,创建 client 建立 SSL 链接时没有做证书验证 ;
SSLFactory sslFactory = SSLFactory.builder().withUnsafeTrustMaterial().withUnsafeHostnameVerifier().build();
builder = builder.setHttpClientConfigCallback(
httpClientBuilder -\> httpClientBuilder.setDefaultCredentialsProvider(credentialsProvider)
setSSLContext(sslFactory.getSslContext())
.setSSLHostnameVerifier(sslFactory.getHostnameVerifier())
);
RestClient restClient = builder.build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
// And create the API client
ElasticsearchClient esClient = new ElasticsearchClient(transport);
2、通过 apikey 创建客户端
我们在安全目录的管理页面,创建 API key ,如下图:
示例代码如下:
// 自己创建的 apikey
String apiKey = "cnRVUy1Ja0JZYUtuSTRuMG1oRkk6RVFSdTk2T2NRb1cyYVdLRTB4TjktQQ==";
RestClientBuilder builder = RestClient.builder(new HttpHost("localhost", 9200, "https"));
SSLFactory sslFactory = SSLFactory.builder().withUnsafeTrustMaterial().withUnsafeHostnameVerifier().build();
RestClient restClient = builder.setDefaultHeaders(new Header\[\]{new BasicHeader("Authorization", "ApiKey " + apiKey)}).setHttpClientConfigCallback(httpClientBuilder -\> httpClientBuilder.setSSLContext(sslFactory.getSslContext()).setSSLHostnameVerifier(sslFactory.getHostnameVerifier())).build();
// Create the transport with a Jackson mapper
ElasticsearchTransport transport = new RestClientTransport(restClient, new JacksonJsonpMapper());
// And create the API client
ElasticsearchClient esClient = new ElasticsearchClient(transport);
3.3 创建文档 {#3.3-%E5%88%9B%E5%BB%BA%E6%96%87%E6%A1%A3}
创建索引名为products
,新建一个文档 id 为 1 。
ProductPo product = new ProductPo(1, "Bag", 42);
IndexRequest\<Object\> indexRequest = new IndexRequest.Builder\<\>().index("products").id(String.valueOf(product.getId())).document(product).build();
IndexResponse response = esClient.index(indexRequest);
`System.out.println("Indexed with version " + response.version());
`
3.4 查询文档 {#3.4-%E6%9F%A5%E8%AF%A2%E6%96%87%E6%A1%A3}
GetResponse<ProductPo> response = esClient.get(g -> g
.index("products")
.id(String.valueOf(1)),
ProductPo.class
);
`if (response.found()) {
ProductPo product = response.source();
System.out.println("Product name " + product.getName());
} else {
System.out.println("Product not found");
}
`
3.5 修改文档 {#3.5-%E4%BF%AE%E6%94%B9%E6%96%87%E6%A1%A3}
Map<String, Object> doc = new HashMap<String, Object>();
// 文档产品名称调整为 my bike
doc.put("name", "my bike");
doc.put("price", 100);
BulkOperation op = new BulkOperation.Builder().update(
i -\> i.action(new UpdateAction.Builder\<\>().doc(doc).docAsUpsert(true).build()).id("1"))
.build();
`List<BulkOperation> list = Collections.singletonList(op);
BulkResponse response = esClient.bulk(bulkBuilder -> bulkBuilder.index("products").operations(list));
`
3.6 删除文档 {#3.6-%E5%88%A0%E9%99%A4%E6%96%87%E6%A1%A3}
esClient.delete(d -> d.index("products").id("1"));
参考文档: {#%E5%8F%82%E8%80%83%E6%96%87%E6%A1%A3%EF%BC%9A}
1、Elasticsearch 官方文档:
2、Github文档