使用 Java 操作 ES
# 60.使用 Java 操作 ES
在项目中,我们通常是使用编程语言来操作索引库,例如 Java。
# 学习目标
- 能够使用 Java 客户端完成创建、删除索引的操作
- 能够使用 Java 客户端完成文档的增删改的操作
- 能够使用 Java 客户端完成文档的查询操作
- 能够完成文档的分页操作
- 能够完成文档的高亮查询操作
- 能够搭建 Spring Data ElasticSearch 的环境
- 能够完成 Spring Data ElasticSearch 的基本增删改查操作
- 能够掌握基本条件查询的方法命名规则
# 环境准备
创建一个 Maven 工程,准备 Maven 的依赖(主要是前两个重要,其他的是一些日志相关的依赖)
<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>transport</artifactId>
<version>5.6.8</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-to-slf4j</artifactId>
<version>2.13.3</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<version>1.7.32</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-simple</artifactId>
<version>1.7.21</version>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.12</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.6</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.0</version>
</dependency>
</dependencies>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 创建索引库
编写测试方法实现创建索引库
- 创建一个 Settings 对象,相当于是一个配置地对象,主要配置集群的名称。
- 创建一个客户端 Client 对象
- 使用 Client 对象创建一个索引库
- 关闭 Client 对象
写个测试方法:
package com.peterjxl.es;
import org.elasticsearch.client.transport.TransportClient;
import org.elasticsearch.common.settings.Settings;
import org.elasticsearch.common.transport.InetSocketTransportAddress;
import org.elasticsearch.transport.client.PreBuiltTransportClient;
import org.junit.Test;
import java.net.InetAddress;
public class ElasticsearchClientTest {
@Test
public void createIndex() throws Exception {
// 1. 创建一个Settings对象,相当于是一个配置地对象,主要配置集群的名称。
Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
// 2. 创建一个客户端Client对象,相当于是一个连接。
TransportClient client = new PreBuiltTransportClient(settings);
// 除了配置对象,还需要配置连接的地址。注意我们不是使用HTTP形式,用的是TCP形式,所以使用的是TransportClient对象,并且端口是9301。
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301 ));
// 为了保证集群的高可用,我们需要配置多个节点。
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302 ));
client.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303 ));
// 3. 使用Client对象创建一个索引库。admin()是管理的意思,indices()是索引的意思,prepareCreate()是创建的意思,最后get()是执行。
client.admin().indices().prepareCreate("index_hello").get();
// 4. 关闭Client对象
client.close();
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
执行完后:可以看到有这个索引
# 设置 Mappings
步骤和之前类似,只是多了设置 mappings:
- 创建一个 Settings 对象
- 创建一个 Client 对象
- 创建一个 mappings 信息,可以是 JSON,可以是字符串,也可以是 XContextBuilder 对象(ES 提供的,可以用于描述 JSON 信息)
- 使用 Client 向 ES 发送 mappings 信息
- 关闭 Client 对象
测试方法:
@Test
public void setIndexMappings() throws Exception {
// 1. 创建一个Settings对象,相当于是一个配置地对象,主要配置集群的名称。
Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
// 2. 创建一个客户端Client对象,相当于是一个连接。
TransportClient client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301 ))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302 ))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303 ));
XContentBuilder xContentBuilder = XContentFactory.jsonBuilder()
.startObject() // startObject()相当于是一个左大括号 {
.startObject("article")
.startObject("properties")
.startObject("id")
.field("type", "long") //field()相当于是一个键值对,这里的意思是id的类型是long
.field("store", true)
.endObject()
.startObject("title")
.field("type", "text")
.field("store", true)
.field("analyzer", "ik_smart")
.endObject()
.startObject("content")
.field("type", "text")
.field("store", true)
.field("analyzer", "ik_smart")
.endObject()
.endObject()
.endObject()
.endObject(); // endObject()相当于是一个右大括号 }
client.admin().indices().preparePutMapping("index_hello") // preparePutMapping()相当于是一个PUT请求
.setType("article")
.setSource(xContentBuilder) // 设置mapping信息,可以是XContentBuilder对象,可以是 JSON 格式的字符串
.get(); // 执行操作
// 4. 关闭Client对象
client.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
使用 XContextBuilder 和自己手动拼接 JSON 字符串,是差不多的。执行完后,可以在 head 插件中看到结果:
# 添加一个初始化方法
之前我们每个方法都初始化了一次 Client 对象,还是挺麻烦的,我们可以抽取出来:
private TransportClient client;
@Before
public void init() throws Exception {
// 1. 创建一个Settings对象,相当于是一个配置地对象,主要配置集群的名称。
Settings settings = Settings.builder().put("cluster.name", "my-elasticsearch").build();
client = new PreBuiltTransportClient(settings)
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9301 ))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9302 ))
.addTransportAddress(new InetSocketTransportAddress(InetAddress.getByName("127.0.0.1"), 9303 ));
}
@After
public void close() {
client.close();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 添加文档
步骤:
- 创建一个 Settings 对象
- 创建一个 Client 对象
- 创建一个文档对象,创建一个 json 格式的字符串,或者使用 XContentBuilder
- 使用 Client 对象吧文档添加到索引库中
- 关闭 Client
@Test
public void testAddDocument() throws Exception{
XContentBuilder builder = XContentFactory.jsonBuilder()
.startObject()
.field("id", 3L)
.field("title", "关于梦想")
.field("content", "编程对我而言,就像是一颗小小的,微弱的希望的种子,我甚至都不愿意让人看见它。生怕有人看见了便要嘲讽它,它太脆弱了,经不起别人的质疑")
.endObject();
// client.prepareIndex("index_hello", "article", "1")
client.prepareIndex()
.setIndex("index_hello") //设置索引名称
.setType("article") //设置type
.setId("3") //设置文档的id,如果不设置的话,会自动生成一个
.setSource(builder) //设置文档信息
.get();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
可以在 head 插件中看到:
# 添加文档的另一种方式
我们可以使用 Jackson 转换 JSON,更方便点。步骤:
- 创建一个 POJO 类
- 使用工具类把 POJO 转换成 JSON 字符串
- 把文档写入索引库
定义一个 Article 类:
package com.peterjxl.es;
public class Article {
private Long id;
private String title;
private String content;
}
1
2
3
4
5
6
7
2
3
4
5
6
7
要生成 getter 和 setter 方法
写个测试方法:
@Test
public void testAddDocument2() throws Exception {
// 创建一个Article对象,设置对象的属性
Article article = new Article();
article.setId(4L);
article.setTitle("关于买房");
article.setContent("虚假的挥霍:花几千块钱去看看海。真正的挥霍:花100万交个首付买一个名义面积70平,实际面积55平,再还30年贷款的小户型住房");
// 把Article对象转换为JSON格式的字符串
ObjectMapper objectMapper = new ObjectMapper();
String jsonDocument = objectMapper.writeValueAsString(article);
System.out.println(jsonDocument);
// 把文档写入索引库
client.prepareIndex("index_hello", "article", article.getId().toString())
.setSource(jsonDocument, XContentType.JSON)
.get();
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 源码
本项目已将源码上传到 Gitee (opens new window) 和 GitHub (opens new window) 上。并且创建了分支 demo1,读者可以通过切换分支来查看本文的示例代码
上次更新: 2024/10/3 10:01:52