ElasticSearch的JavaAPI简单使用

ES是一个开源的高扩展的分布式全文搜索引擎,是整个Elastic Stack技术栈的核心。它可以近乎实时的存储、检索数据;本身扩展性很好,可以扩展到上百台服务器,处理PB级别的数据。Elasticsearch软件是由Java语言开发的,所以也可以通过Java API的方式对Elasticsearch服务进行访问,并且操作的方式基本和Http操作一致

本文已经收录到Github: github.com/chenliang15…

Maven依赖

  • pom.xml中加入ES需要的依赖
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
xml复制代码<dependencies>
<dependency>
<groupId>org.elasticsearch</groupId>
<artifactId>elasticsearch</artifactId>
<version>7.8.0</version>
</dependency>
<!-- elasticsearch的客户端 -->
<dependency>
<groupId>org.elasticsearch.client</groupId>
<artifactId>elasticsearch-rest-high-level-client</artifactId>
<version>7.8.0</version>
</dependency>
<!-- elasticsearch依赖2.x的log4j -->
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-api</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.8.2</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9</version>
</dependency>
<!-- junit单元测试 -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
</dependencies>
  • 如果在运行时报错
1
makefile复制代码java.lang.NoSuchMethodError: org.elasticsearch.client.Request.addParameters

那么应该是发生了依赖冲突,新建一个Maven项目,最好不要直接创建springboot项目,可能会有依赖冲突,将上面的依赖加入到maven项目的pom中

链接ES客户端

因为使用的highLevel的ES客户端,所以可以很方便的连接到ES,只需要通过host和port就可以直接连接

1
2
3
4
5
6
7
java复制代码public static void main(String[] args) throws IOException {
RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

esClient.close();
}

如果代码执行正常,没有报错那么就表示正常连接到了ES节点,可以通过获取到的RestHighLevelClient对象进行操作

索引操作

加入了maven依赖,那么就可以通过Java客户端链接到ES进行操作,首先进行索引的基本操作

  • 创建索引
1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);
@Test
public void index_create() throws IOException {
// 创建索引 - 请求对象
CreateIndexRequest request = new CreateIndexRequest("test");
// 发送请求,获取响应
CreateIndexResponse response = esClient.indices().create(request, RequestOptions.DEFAULT);
boolean acknowledged = response.isAcknowledged();
// 响应状态
System.out.println("操作状态 = " + acknowledged);
}
  • 查询索引
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

@Test
public void index_get() throws IOException {

GetIndexRequest request = new GetIndexRequest("test");

GetIndexResponse response = esClient.indices().get(request, RequestOptions.DEFAULT);

System.out.println(Arrays.toString(response.getIndices()));
System.out.println(response.getMappings());
System.out.println(response.getSettings());
}
  • 删除索引
1
2
3
4
5
6
7
8
9
10
11
12
13
java复制代码RestHighLevelClient esClient = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http"))
);

@Test
public void index_delete() throws IOException {

DeleteIndexRequest request = new DeleteIndexRequest("test");

AcknowledgedResponse response = esClient.indices().delete(request, RequestOptions.DEFAULT);

System.out.println(response.isAcknowledged());
}

文档操作

文档作为数据的对象,可以通过ES的客户端对象直接操作

RestHighLevelClient对象和上面的创建方式相同,此处省略

文档基本操作
  • 创建文档
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
java复制代码@Test
public void doc_create() throws IOException {
IndexRequest request = new IndexRequest();
// 设置操作的索引和当前插入的文档的id
request.index("people").id("1001");

User user = new User();
user.setName("张三");
user.setAge(10);
user.setSex("男");

ObjectMapper mapper = new ObjectMapper();
String userJson = mapper.writeValueAsString(user);

request.source(userJson, XContentType.JSON);

IndexResponse response = esClient.index(request, RequestOptions.DEFAULT);

System.out.println(response);

System.out.println("_index" + response.getIndex());
System.out.println("_id" + response.getId());
System.out.println("_result" + response.getResult());
}
  • 更新文档
1
2
3
4
5
6
7
8
9
10
11
java复制代码@Test
public void doc_update() throws IOException {
UpdateRequest request = new UpdateRequest();
request.index("people").id("1001");

request.doc(XContentType.JSON, "sex", "女");

UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);

System.out.println(response);
}
  • 查询文档
1
2
3
4
5
6
7
8
9
10
11
java复制代码@Test
public void doc_get() throws IOException {

GetRequest request = new GetRequest();
request.index("people").id("1001");

GetResponse response = esClient.get(request, RequestOptions.DEFAULT);

System.out.println(response);
System.out.println(response.getSource());
}
  • 删除文档
1
2
3
4
5
6
7
8
java复制代码@Test
public void doc_delete() throws IOException {
DeleteRequest request = new DeleteRequest();
request.index("people").id("1001");

DeleteResponse response = esClient.delete(request, RequestOptions.DEFAULT);
System.out.println(response);
}
文档批量操作

一般操作ES的数据都是批量保存或者批量删除,如果通过一条一条的操作,那么效率非常的低,可以通过批量操作API提高效率

  • 批量保存
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
java复制代码@Test
public void doc_insert_batch() throws IOException {
BulkRequest request = new BulkRequest();
request.add(new IndexRequest().index("people").id("1001").source(XContentType.JSON, "name", "张三", "sex", "男", "age", 10));
request.add(new IndexRequest().index("people").id("1002").source(XContentType.JSON, "name", "李四", "sex", "男", "age", 11));
request.add(new IndexRequest().index("people").id("1003").source(XContentType.JSON, "name", "王五", "sex", "男", "age", 12));
request.add(new IndexRequest().index("people").id("1004").source(XContentType.JSON, "name", "王五1", "sex", "男", "age", 8));
request.add(new IndexRequest().index("people").id("1005").source(XContentType.JSON, "name", "王五2", "sex", "男", "age", 9));
request.add(new IndexRequest().index("people").id("1006").source(XContentType.JSON, "name", "王五33", "sex", "男", "age", 7));

BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);

System.out.println(response.getTook());
System.out.println(Arrays.toString(response.getItems()));
}
  • 批量删除
1
2
3
4
5
6
7
8
9
10
11
12
java复制代码@Test
public void doc_delete_batch() throws IOException {
BulkRequest request = new BulkRequest();
request.add(new DeleteRequest().index("people").id("1001"));
request.add(new DeleteRequest().index("people").id("1002"));
request.add(new DeleteRequest().index("people").id("1003"));

BulkResponse response = esClient.bulk(request, RequestOptions.DEFAULT);

System.out.println(response.getTook());
System.out.println(response);
}

文档高级查询

高级查询、分组查询、分页、排序、聚合操作等,作为ES常用的查询操作,ES的Java客户端也提供了好用的API进行操作

  • 查询指定索引的所有数据
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
java复制代码@Test
public void match_all() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • term查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
java复制代码@Test
public void query_term() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.termQuery("age", 10));

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • 分页查询
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
java复制代码@Test
public void query_page() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());

// from指定的是页数开始的偏移量, (当前页数 - 1)* size
builder.from(0);
builder.size(3);

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • 排序查询
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
java复制代码@Test
public void query_sort() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());

builder.sort("age", SortOrder.DESC);
request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • 查询并过滤字段
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
java复制代码@Test
public void query_filter() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();
builder.query(QueryBuilders.matchAllQuery());

String[] excludes = {};
String[] includes = {"name"};
// 过滤字段,指定只包含某些字段,或者需要排除某些字段
builder.fetchSource(includes, excludes);

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • bool条件查询,多条件Must
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
java复制代码@Test
public void query_bool_must() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

// 多条件查询,must -> 一定需要匹配到
boolQueryBuilder.must(QueryBuilders.matchQuery("age", 10));
boolQueryBuilder.must(QueryBuilders.matchQuery("sex", "女"));


builder.query(boolQueryBuilder);

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • bool条件查询,多条件should
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
java复制代码@Test
public void query_bool_should() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();

BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();

// 多条件查询,should -> 如果当前这条数据满足两个should条件中的任意一个,则表示满足条件
boolQueryBuilder.should(QueryBuilders.matchQuery("age", 10));
boolQueryBuilder.should(QueryBuilders.matchQuery("sex", "女"));

builder.query(boolQueryBuilder);

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • 范围查询
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
java复制代码@Test
public void query_range() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();

// 根据某个字段构建范围查询
RangeQueryBuilder rangeQueryBuilder = QueryBuilders.rangeQuery("age");

// 指定范围查询的条件数据
rangeQueryBuilder.gte(9);
rangeQueryBuilder.lte(12);

builder.query(rangeQueryBuilder);

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • 模糊查询
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
java复制代码@Test
public void query_fuzzy() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();

// 模糊查询,指定字段名称进行模糊查询,后面的指定模糊匹配的字符个数
builder.query(QueryBuilders.fuzzyQuery("name", "王五").fuzziness(Fuzziness.ONE));

request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);

SearchHits hits = response.getHits();
System.out.println("took:" + response.getTook());
System.out.println("timeout:" + response.isTimedOut());
System.out.println("total:" + hits.getTotalHits());
System.out.println("MaxScore:" + hits.getMaxScore());
System.out.println("hits========>>");
for (SearchHit hit : hits) {
//输出每条查询的结果信息
System.out.println(hit.getSourceAsString());
}
System.out.println("<<========");
}
  • 高亮查询
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
java复制代码@Test
public void query_highlight() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();
TermsQueryBuilder termsQueryBuilder = QueryBuilders.termsQuery("sex", "女");

// 设置查询方式
builder.query(termsQueryBuilder);

// 构建高亮字段
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font color='red'>"); // 设置标签前缀
highlightBuilder.postTags("</font>"); // 设置标签后缀
highlightBuilder.field("sex"); // 设置高亮字段

// 设置高亮查询
builder.highlighter(highlightBuilder);

// 设置请求体
request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
System.out.println(response);
SearchHits hits = response.getHits();
System.out.println("took::"+response.getTook());
System.out.println("time_out::"+response.isTimedOut());
System.out.println("total::"+hits.getTotalHits());
System.out.println("max_score::"+hits.getMaxScore());
System.out.println("hits::::>>");
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
System.out.println(sourceAsString);
//打印高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
System.out.println(highlightFields);
}
}
  • 聚合查询—最大值
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
java复制代码@Test
public void query_aggs_max() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();

// 聚合查询,获取最大的age字段的数
builder.aggregation(AggregationBuilders.max("maxAge").field("age"));

// 设置请求体
request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
System.out.println(response);
}
  • 聚合查询—分组查询
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
java复制代码@Test
public void query_aggs_group() throws IOException {
SearchRequest request = new SearchRequest();
request.indices("people");

SearchSourceBuilder builder = new SearchSourceBuilder();

// 聚合查询,获取最大的age字段的数
builder.aggregation(AggregationBuilders.terms("age_groupby").field("age"));

// 设置请求体
request.source(builder);

SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
System.out.printl n(response);
}

文档的高级查询,JavaAPI的操作方式和语法基本和Http操作的一致,只不过将对应的Http方式替换为了API,可以更好的在程序中进行ES操作,下一篇一起看看如何在SpringBoot和ElasticSearch进行集成吧,更加方便的操作ES与索引数据

本文转载自: 掘金

开发者博客 – 和开发相关的 这里全都有

0%