【ElasticSearch 学习笔记】Java API
JavaAPI - 环境准备。JavaAPI - 索引操作:创建索引、查询索引、删除索引JavaAPI - 文档基本操作:新增文档、修改文档、查询文档、删除文档、批量新增、批量删除JavaAPI - 文档高级查询、封装、全量查询、条件查询、分页查询、查询排序、组合查询、范围查询、模糊查询、高亮查询、最大值查询、分组查询
·
ElasticSearch Java API
学习视频:ElasticSearch 教程入门到精通(基于 ELK 技术栈 elasticsearch 7.8.x 版本)
学习大纲:
- 第 1 章 Elasticsearch 概述
- 第 2 章 Elasticsearch 入门
- 第 3 章 Elasticsearch 环境
- 第 4 章 Elasticsearch 进阶
- 第 5 章 Elasticsearch 集成
- 第 6 章 Elasticsearch 优化
- 第 7 章 Elasticsearch 面试题
第 2 章 ElasticSearch 入门
JavaAPI - 环境准备
新建一个 Maven 工程,添加以下依赖:
<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>
HelloElasticsearch
import java.io.IOException;
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
public class HelloElasticsearch {
public static void main(String[] args) throws IOException {
// 创建客户端对象
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http")));
// ...
System.out.println(client);
// 关闭客户端连接
client.close();
}
}
JavaAPI - 索引操作
创建索引
import org.apache.http.HttpHost;
import org.elasticsearch.action.admin.indices.create.CreateIndexRequest;
import org.elasticsearch.action.admin.indices.create.CreateIndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import java.io.IOException;
public class CreateIndex {
public static void main(String[] args) throws IOException {
// 创建客户端对象
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http")));
// 创建索引 - 请求对象
CreateIndexRequest request = new CreateIndexRequest("user");
// 发送请求,获取响应
CreateIndexResponse response = client.indices()
.create(request, RequestOptions.DEFAULT);
boolean acknowledged = response.isAcknowledged();
// 响应状态
System.out.println("操作状态 = " + acknowledged);
// 关闭客户端连接
client.close();
}
}
查询索引
public class SearchIndex {
public static void main(String[] args) throws IOException {
// 创建客户端对象
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http")));
// 查询索引 - 请求对象
GetIndexRequest request = new GetIndexRequest("user");
// 发送请求,获取响应
GetIndexResponse response = client.indices()
.get(request, RequestOptions.DEFAULT);
System.out.println("aliases:" + response.getAliases());
System.out.println("mappings:" + response.getMappings());
System.out.println("settings:" + response.getSettings());
client.close();
}
}
控制台输出:
aliases:{user=[]}
mappings:{user=org.elasticsearch.cluster.metadata.MappingMetadata@e9e63037}
settings:{user={"index.creation_date":"1646888783599","index.number_of_replicas":"1","index.number_of_shards":"1","index.provided_name":"user","index.uuid":"uN9XtaJBT2O_sjwMdH06MQ","index.version.created":"7080099"}}
删除索引
public class DeleteIndex {
public static void main(String[] args) throws IOException {
RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http")));
// 删除索引 - 请求对象
DeleteIndexRequest request = new DeleteIndexRequest("user");
// 发送请求,获取响应
AcknowledgedResponse response = client.indices()
.delete(request, RequestOptions.DEFAULT);
// 操作结果
System.out.println("操作结果:" + response.isAcknowledged());
client.close();
}
}
控制台输出:
操作结果:true
JavaAPI - 文档基本操作
重构
对 ElasticSearch 的连接和关闭进行重构:
import org.elasticsearch.client.RestHighLevelClient;
@FunctionalInterface
public interface ElasticsearchTask {
void doSomething(RestHighLevelClient client) throws Exception;
}
import org.apache.http.HttpHost;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
public class ConnectElasticsearch {
public static void connect(ElasticsearchTask task) {
// 创建客户端对象,并自动关闭连接
try (RestHighLevelClient client = new RestHighLevelClient(
RestClient.builder(new HttpHost("localhost", 9200, "http")))) {
task.doSomething(client);
} catch (Exception e) {
e.printStackTrace();
}
}
}
想要 ElasticSearch 完成一些操作,只要编写一个 lambda 即可:
public class SomeClass {
public static void main(String[] args) {
ConnectElasticsearch.connect(client -> {
//do something
});
}
}
新增文档
import com.fasterxml.jackson.databind.ObjectMapper;
import com.yu.es.test.model.User;
import com.yu.es.test.utils.ConnectElasticsearch;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.xcontent.XContentType;
public class InsertDoc {
public static void main(String[] args) {
ConnectElasticsearch.connect(client -> {
// 新增文档 - 请求对象
IndexRequest request = new IndexRequest();
// 设置索引及唯一性标识
request.index("user").id("1001");
// 创建数据对象
User user = new User();
user.setName("zhangsan");
user.setAge(30);
user.setSex("男");
// Model -> JSON
ObjectMapper objectMapper = new ObjectMapper();
String productJson = objectMapper.writeValueAsString(user);
// 添加文档数据,数据格式为 JSON 格式
request.source(productJson, XContentType.JSON);
// 客户端发送请求,获取响应对象
IndexResponse response = client.index(request, RequestOptions.DEFAULT);
// 打印结果信息
System.out.println("_index:" + response.getIndex());
System.out.println("_id:" + response.getId());
System.out.println("_result:" + response.getResult());
});
}
}
控制台输出:
_index:user
_id:1001
_result:CREATED
修改文档
import com.yu.es.test.utils.ConnectElasticsearch;
import org.elasticsearch.action.update.UpdateRequest;
import org.elasticsearch.action.update.UpdateResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.xcontent.XContentType;
public class UpdateDoc {
public static void main(String[] args) {
ConnectElasticsearch.connect(client -> {
// 修改文档 - 请求对象
UpdateRequest request = new UpdateRequest();
// 配置修改参数
request.index("user").id("1001");
// 设置请求体,对数据进行修改
request.doc(XContentType.JSON, "sex", "女");
// 客户端发送请求,获取响应对象
UpdateResponse response = client.update(request, RequestOptions.DEFAULT);
System.out.println("_index:" + response.getIndex());
System.out.println("_id:" + response.getId());
System.out.println("_result:" + response.getResult());
});
}
}
控制台输出:
_index:user
_id:1001
_result:UPDATED
查询文档
import com.yu.es.test.utils.ConnectElasticsearch;
import org.elasticsearch.action.get.GetRequest;
import org.elasticsearch.action.get.GetResponse;
import org.elasticsearch.client.RequestOptions;
public class GetDoc {
public static void main(String[] args) {
ConnectElasticsearch.connect(client -> {
// 1.创建请求对象
GetRequest request = new GetRequest().index("user").id("1001");
// 2.客户端发送请求,获取响应对象
GetResponse response = client.get(request, RequestOptions.DEFAULT);
// 3.打印结果信息
System.out.println("_index:" + response.getIndex());
System.out.println("_type:" + response.getType());
System.out.println("_id:" + response.getId());
System.out.println("source:" + response.getSourceAsString());
});
}
}
控制台输出:
_index:user
_type:_doc
_id:1001
source:{"name":"zhangsan","sex":"女","age":30}
删除文档
import com.yu.es.test.utils.ConnectElasticsearch;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.client.RequestOptions;
public class DeleteDoc {
public static void main(String[] args) {
ConnectElasticsearch.connect(client -> {
// 1.创建请求对象
DeleteRequest request = new DeleteRequest().index("user").id("1001");
// 2.客户端发送请求,获取响应对象
DeleteResponse response = client.delete(request, RequestOptions.DEFAULT);
// 3.打印信息
System.out.println(response.toString());
});
}
}
控制台输出:
DeleteResponse[index=user,type=_doc,id=1001,version=3,result=deleted,shards=ShardInfo{total=2, successful=1, failures=[]}]
批量新增
import com.yu.es.test.utils.ConnectElasticsearch;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.common.xcontent.XContentType;
public class BatchInsertDoc {
public static void main(String[] args) {
ConnectElasticsearch.connect(client -> {
// 创建批量新增请求对象
BulkRequest request = new BulkRequest();
request.add(new IndexRequest().index("user").id("1001")
.source(XContentType.JSON, "name", "zhangsan", "age", 30));
request.add(new IndexRequest().index("user").id("1002")
.source(XContentType.JSON, "name", "lisi"));
request.add(new IndexRequest().index("user").id("1003")
.source(XContentType.JSON, "name", "wangwu"));
// 客户端发送请求,获取响应对象
BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
// 打印结果信息
System.out.println("took:" + responses.getTook());
System.out.println("items:" + responses.getItems());
});
}
}
批量删除
import com.yu.es.test.utils.ConnectElasticsearch;
import org.elasticsearch.action.bulk.BulkRequest;
import org.elasticsearch.action.bulk.BulkResponse;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.client.RequestOptions;
public class BatchDelDoc {
public static void main(String[] args) {
ConnectElasticsearch.connect(client -> {
// 创建批量删除请求对象
BulkRequest request = new BulkRequest();
request.add(new DeleteRequest().index("user").id("1001"));
request.add(new DeleteRequest().index("user").id("1002"));
request.add(new DeleteRequest().index("user").id("1003"));
// 客户端发送请求,获取响应对象
BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
// 打印结果信息
System.out.println("took:" + responses.getTook());
System.out.println("items:" + responses.getItems());
});
}
}
JavaAPI - 文档高级查询
注意:
matchQuery
分词搜索termQuery
完全匹配搜索
先批量新增数据:
public class BatchInsertDoc {
public static void main(String[] args) {
ConnectElasticsearch.connect(client -> {
// 创建批量新增请求对象
BulkRequest request = new BulkRequest();
request.add(new IndexRequest().index("user").id("1001")
.source(XContentType.JSON, "name", "zhangsan", "age", "10", "sex", "女"));
request.add(new IndexRequest().index("user").id("1002")
.source(XContentType.JSON, "name", "lisi", "age", "30", "sex", "女"));
request.add(new IndexRequest().index("user").id("1003")
.source(XContentType.JSON, "name", "wangwu1", "age", "40", "sex", "男"));
request.add(new IndexRequest().index("user").id("1004")
.source(XContentType.JSON, "name", "wangwu2", "age", "20", "sex", "女"));
request.add(new IndexRequest().index("user").id("1005")
.source(XContentType.JSON, "name", "wangwu3", "age", "50", "sex", "男"));
request.add(new IndexRequest().index("user").id("1006")
.source(XContentType.JSON, "name", "wangwu4", "age", "20", "sex", "男"));
// 客户端发送请求,获取响应对象
BulkResponse responses = client.bulk(request, RequestOptions.DEFAULT);
// 打印结果信息
System.out.println("took:" + responses.getTook());
System.out.println("items:" + responses.getItems());
});
}
}
封装
以下操作基本模板都是一样的,不同的就是各种查询的构建过程不同:
// 创建搜索请求对象
SearchRequest request = new SearchRequest();
request.indices("user");
// 构建查询的请求体
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 构建....
// 这一块的代码需要根据具体需求来写
// 输出查询结果
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("<<========");
因此我们将该过程封装一下:
public class QueryDoc {
@FunctionalInterface
public interface QueryBuild {
void doBuild(SearchRequest request, SearchSourceBuilder sourceBuilder) throws IOException;
}
public static void doQuery(RestHighLevelClient client, QueryBuild build) throws IOException {
// 创建搜索请求对象
SearchRequest request = new SearchRequest();
request.indices("user");
// 构建查询的请求体
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 请求体的构建由调用者进行
build.doBuild(request, sourceBuilder);
request.source(sourceBuilder);
SearchResponse response = client.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("<<========");
}
}
使用方法:(后面的示例省略 main 方法中调用)
public static final ElasticsearchTask SEARCH_ALL = client -> {
doQuery(client, (request, sourceBuilder) -> {
// 全量查询
sourceBuilder.query(QueryBuilders.matchAllQuery());
});
};
public static void main(String[] args) {
ConnectElasticsearch.connect(SEARCH_ALL); // 全量查询
}
全量查询
示例:查询所有索引数据
public static final ElasticsearchTask SEARCH_ALL = client -> {
doQuery(client, (request, sourceBuilder) -> {
// 查询全部
sourceBuilder.query(QueryBuilders.matchAllQuery());
});
};
took:2ms
timeout:false
total:6 hits
MaxScore:1.0
hits========>>
{"name":"zhangsan","age":"10","sex":"女"}
{"name":"lisi","age":"30","sex":"女"}
{"name":"wangwu1","age":"40","sex":"男"}
{"name":"wangwu2","age":"20","sex":"女"}
{"name":"wangwu3","age":"50","sex":"男"}
{"name":"wangwu4","age":"20","sex":"男"}
<<========
条件查询
示例:查询年龄为 30 的索引数据
public static final ElasticsearchTask SEARCH_BY_CONDITION = client -> {
doQuery(client, (request, sourceBuilder) -> {
// 查询条件:age = 30
sourceBuilder.query(QueryBuilders.termQuery("age", "30"));
});
};
took:10ms
timeout:false
total:1 hits
MaxScore:1.0
hits========>>
{"name":"lisi","age":"30","sex":"女"}
<<========
分页查询
示例:每页 2 条数据,查询第 1 页的数据
public static final ElasticsearchTask SEARCH_BY_PAGING = client -> {
doQuery(client, (request, sourceBuilder) -> {
// 当前页起始索引(第一条数据的顺序号) from
sourceBuilder.from(0);
// 每页显示多少条 size
sourceBuilder.size(2);
});
};
took:2ms
timeout:false
total:6 hits
MaxScore:1.0
hits========>>
{"name":"zhangsan","age":"10","sex":"女"}
{"name":"lisi","age":"30","sex":"女"}
<<========
查询排序
public static final ElasticsearchTask SEARCH_WITH_ORDER = client -> {
doQuery(client, (request, sourceBuilder) -> {
// 查询全部
sourceBuilder.query(QueryBuilders.matchAllQuery());
// 年龄升序
sourceBuilder.sort("age", SortOrder.ASC);
});
};
took:57ms
timeout:false
total:6 hits
MaxScore:NaN
hits========>>
{"name":"zhangsan","age":"10","sex":"女"}
{"name":"wangwu2","age":"20","sex":"女"}
{"name":"wangwu4","age":"20","sex":"男"}
{"name":"lisi","age":"30","sex":"女"}
{"name":"wangwu1","age":"40","sex":"男"}
{"name":"wangwu3","age":"50","sex":"男"}
<<========
组合查询
public static final ElasticsearchTask SEARCH_BY_BOOL_CONDITION = client -> {
doQuery(client, (request, sourceBuilder) -> {
BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
// 必须包含: age = 30
boolQueryBuilder.must(QueryBuilders.matchQuery("age", "30"));
// 一定不含:name = zhangsan
boolQueryBuilder.mustNot(QueryBuilders.matchQuery("name", "zhangsan"));
// 可能包含: sex = 男
boolQueryBuilder.should(QueryBuilders.matchQuery("sex", "男"));
sourceBuilder.query(boolQueryBuilder);
});
};
took:2ms
timeout:false
total:1 hits
MaxScore:1.0
hits========>>
{"name":"lisi","age":"30","sex":"女"}
<<========
范围查询
public static final ElasticsearchTask SEARCH_BY_RANGE = client -> {
doQuery(client, (request, sourceBuilder) -> {
RangeQueryBuilder rangeQuery = QueryBuilders.rangeQuery("age");
// rangeQuery.gte("30"); // age 大于等于 30
rangeQuery.lte("40"); // age 小于等于 40
sourceBuilder.query(rangeQuery);
});
};
took:7ms
timeout:false
total:5 hits
MaxScore:1.0
hits========>>
{"name":"zhangsan","age":"10","sex":"女"}
{"name":"lisi","age":"30","sex":"女"}
{"name":"wangwu1","age":"40","sex":"男"}
{"name":"wangwu2","age":"20","sex":"女"}
{"name":"wangwu4","age":"20","sex":"男"}
<<========
模糊查询
public static final ElasticsearchTask SEARCH_BY_FUZZY_CONDITION = client -> {
doQuery(client, (request, sourceBuilder) -> {
// 模糊查询: name 包含 wangwu 的数据
sourceBuilder.query(
QueryBuilders.fuzzyQuery("name", "wangwu").fuzziness(Fuzziness.ONE));
});
};
took:5ms
timeout:false
total:4 hits
MaxScore:1.2837042
hits========>>
{"name":"wangwu1","age":"40","sex":"男"}
{"name":"wangwu2","age":"20","sex":"女"}
{"name":"wangwu3","age":"50","sex":"男"}
{"name":"wangwu4","age":"20","sex":"男"}
<<========
高亮查询
public static final ElasticsearchTask SEARCH_WITH_HIGHLIGHT = client -> {
SearchRequest request = new SearchRequest().indices("user");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
// 构建查询方式:高亮查询
TermsQueryBuilder termsQueryBuilder =
QueryBuilders.termsQuery("name", "zhangsan");
// 设置查询方式
sourceBuilder.query(termsQueryBuilder);
// 构建高亮字段
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.preTags("<font color='red'>"); // 设置标签前缀
highlightBuilder.postTags("</font>"); // 设置标签后缀
highlightBuilder.field("name"); // 设置高亮字段
// 设置高亮构建对象
sourceBuilder.highlighter(highlightBuilder);
// 设置请求体
request.source(sourceBuilder);
// 客户端发送请求,获取响应对象
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
SearchHits hits = response.getHits();
for (SearchHit hit : hits) {
String sourceAsString = hit.getSourceAsString();
System.out.println(sourceAsString);
// 打印高亮结果
Map<String, HighlightField> highlightFields = hit.getHighlightFields();
System.out.println(highlightFields);
}
};
{"name":"zhangsan","age":"10","sex":"女"}
{name=[name], fragments[[<font color='red'>zhangsan</font>]]}
最大值查询
public static final ElasticsearchTask SEARCH_WITH_MAX = client -> {
SearchRequest request = new SearchRequest().indices("user");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.aggregation(AggregationBuilders.max("maxAge").field("age"));
request.source(sourceBuilder);
// 客户端发送请求,获取响应对象
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println(response);
};
{
..., // 省略
"aggregations": {
"max#maxAge": {
"value": 50.0
}
}
}
分组查询
public static final ElasticsearchTask SEARCH_WITH_GROUP = client -> {
SearchRequest request = new SearchRequest().indices("user");
SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
sourceBuilder.aggregation(AggregationBuilders.terms("age_groupby").field("age"));
request.source(sourceBuilder);
// 客户端发送请求,获取响应对象
SearchResponse response = client.search(request, RequestOptions.DEFAULT);
System.out.println(response);
};
{
..., // 省略
"aggregations": {
"lterms#age_groupby": {
"doc_count_error_upper_bound": 0,
"sum_other_doc_count": 0,
"buckets": [{
"key": 20,
"doc_count": 2
}, {
"key": 10,
"doc_count": 1
}, {
"key": 30,
"doc_count": 1
}, {
"key": 40,
"doc_count": 1
}, {
"key": 50,
"doc_count": 1
}]
}
}
}
更多推荐
已为社区贡献7条内容
所有评论(0)