飞道的博客

【微服务】java 操作elasticsearch详细总结

802人阅读  评论(0)

一、前言

上一篇我们通过kibana的可视化界面,对es的索引以及文档的常用操作做了毕竟详细的总结,本篇将介绍如何使用java完成对es的操作,这也是实际开发中将要涉及到的。

二、java操作es的常用模式

目前,开发中使用java操作es,不管是框架集成,还是纯粹的使用es的api,主要通过下面两种方式:

  • rest-api,主流的像  RestHighLevelClient ;

  • 与springboot集成时的jpa操作,主要是 ElasticsearchRepository 相关的api;

上面两种模式的api在开发中都可以方便的使用,相比之下,RestHighLevelClient相关的api灵活性更高,而ElasticsearchRepository 底层做了较多的封装,学习和使用的成本更低,上手更快。

接下来将对上面的两种操作模式做一个详细的总结,本篇所述的es基于7.6.2版本,配合的kibana也为7.6.2版本。

三、rest-api 操作

1、前置准备

导入依赖

导入核心依赖,主要是es的rest依赖,其他的可以根据自己的需要导入; 


  
  1. <dependencies>
  2. <dependency>
  3. <groupId>org.apache.logging.log4j</groupId>
  4. <artifactId>log4j-api</artifactId>
  5. <version> 2.11 .2</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>org.apache.logging.log4j</groupId>
  9. <artifactId>log4j-core</artifactId>
  10. <version> 2.11 .2</version>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.apache.logging.log4j</groupId>
  14. <artifactId>log4j-core</artifactId>
  15. <version> 2.8 .2</version>
  16. </dependency>
  17. <dependency>
  18. <groupId>org.apache.logging.log4j</groupId>
  19. <artifactId>log4j-jcl</artifactId>
  20. <version> 2.11 .2</version>
  21. </dependency>
  22. <dependency>
  23. <groupId>commons-logging</groupId>
  24. <artifactId>commons-logging</artifactId>
  25. <version> 1.2</version>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.elasticsearch</groupId>
  29. <artifactId>elasticsearch</artifactId>
  30. <version> 7.6 .2</version>
  31. </dependency>
  32. <dependency>
  33. <groupId>org.elasticsearch.client</groupId>
  34. <artifactId>elasticsearch-rest-high-level-client</artifactId>
  35. <version> 7.6 .2</version>
  36. </dependency>
  37. <dependency>
  38. <groupId>com.fasterxml.jackson.core</groupId>
  39. <artifactId>jackson-databind</artifactId>
  40. <version> 2.9 .9</version>
  41. </dependency>
  42. <dependency>
  43. <groupId>junit</groupId>
  44. <artifactId>junit</artifactId>
  45. <version> 4.12</version>
  46. </dependency>
  47. </dependencies>

es连接测试

为了确保后续的所有实验能够正常进行,建议先通过下面的程序测试下是否能够连接es服务;


  
  1. import org.apache.http.HttpHost;
  2. import org.elasticsearch.client.RestClient;
  3. import org.elasticsearch.client.RestHighLevelClient;
  4. import java.io.IOException;
  5. public class EsClientTest {
  6. public static void main (String[] args) throws IOException {
  7. RestHighLevelClient esClient = new RestHighLevelClient(
  8. RestClient.builder( new HttpHost( "IP", 9200, "http"))
  9. );
  10. System.out.println( "success");
  11. esClient.close();
  12. }
  13. }

运行上面的代码,出现下面的效果说明连接成功

2、索引相关操作api的使用

为了减少连接相关的编码,我们将es的client提出到全局的静态变量中,其他方法中就可以直接引用了


  
  1. public static RestHighLevelClient esClient;
  2. static {
  3. esClient = new RestHighLevelClient(
  4. RestClient.builder( new HttpHost( "IP", 9200, "http"))
  5. );
  6. }

2.1  创建索引


  
  1. /**
  2. * 创建索引
  3. * @throws IOException
  4. */
  5. public static void createIndex () throws IOException {
  6. CreateIndexRequest createIndexRequest = new CreateIndexRequest( "user");
  7. CreateIndexResponse indexResponse = esClient.indices().create(createIndexRequest, RequestOptions.DEFAULT);
  8. boolean acknowledged = indexResponse.isAcknowledged();
  9. System.out.println( "索引创建状态:" + acknowledged);
  10. }

main方法中调用方法即可


  
  1. public static void main (String[] args) throws IOException {
  2. System.out.println( "connect success");
  3. createIndex();
  4. esClient.close();
  5. }

运行main创建索引

通过kibana查询确认索引是否创建成功

2.2  获取索引


  
  1. /**
  2. * 索引信息查询
  3. * @throws IOException
  4. */
  5. public static void getIndex () throws IOException {
  6. GetIndexRequest getIndexRequest = new GetIndexRequest( "user");
  7. GetIndexResponse getIndexResponse = esClient.indices().get(getIndexRequest, RequestOptions.DEFAULT);
  8. System.out.println(getIndexResponse.getAliases());
  9. System.out.println(getIndexResponse.getMappings());
  10. System.out.println(getIndexResponse.getSettings());
  11. }

2.3  删除索引


  
  1. /**
  2. * 删除索引
  3. * @throws IOException
  4. */
  5. public static void deleteIndex () throws IOException {
  6. DeleteIndexRequest getIndexRequest = new DeleteIndexRequest( "user");
  7. AcknowledgedResponse delete = esClient.indices().delete(getIndexRequest, RequestOptions.DEFAULT);
  8. System.out.println( "索引删除状态:" + delete.isAcknowledged());
  9. }

3、文档常用操作api的使用

在实际开发过程中,对于文档的操作更为的频繁,接下来演示与es文档相关的操作api。

前置准备


  
  1. public static ObjectMapper objectMapper = new ObjectMapper();
  2. public static RestHighLevelClient esClient;
  3. static {
  4. esClient = new RestHighLevelClient(
  5. RestClient.builder( new HttpHost( "IP", 9200, "http"))
  6. );
  7. }

用于测试使用的对象


  
  1. public class User {
  2. private String name;
  3. private String sex;
  4. private Integer age;
  5. private Integer salary;
  6. public User () {
  7. }
  8. public User (String name, String sex, Integer age, Integer salary) {
  9. this.name = name;
  10. this.sex = sex;
  11. this.age = age;
  12. this.salary = salary;
  13. }
  14. public Integer getSalary () {
  15. return salary;
  16. }
  17. public void setSalary (Integer salary) {
  18. this.salary = salary;
  19. }
  20. public String getName () {
  21. return name;
  22. }
  23. public void setName (String name) {
  24. this.name = name;
  25. }
  26. public String getSex () {
  27. return sex;
  28. }
  29. public void setSex (String sex) {
  30. this.sex = sex;
  31. }
  32. public Integer getAge () {
  33. return age;
  34. }
  35. public void setAge (Integer age) {
  36. this.age = age;
  37. }
  38. }

3.1  索引添加文档

注意:实际开发中,user对象应该作为参数传入【可以基于此做进一步的封装】


  
  1. /**
  2. * 添加数据
  3. * @throws Exception
  4. */
  5. public static void add () throws Exception{
  6. IndexRequest indexRequest = new IndexRequest();
  7. indexRequest.index( "user").id( "1008");
  8. User user = new User();
  9. user.setName( "孙二娘");
  10. user.setAge( 23);
  11. user.setSex( "女");
  12. user.setSalary( 7000);
  13. String userData = objectMapper.writeValueAsString(user);
  14. indexRequest.source(userData,XContentType.JSON);
  15. //插入数据
  16. IndexResponse response = esClient.index(indexRequest, RequestOptions.DEFAULT);
  17. System.out.println(response.status());
  18. System.out.println(response.getResult());
  19. }

在main方法调用执行下该方法


  
  1. public static void main (String[] args) throws Exception {
  2. add();
  3. esClient.close();
  4. }

可以通过kibana查询检查下数据是否添加成功

3.2  修改文档


  
  1. /**
  2. * 修改数据
  3. * @throws Exception
  4. */
  5. public static void update () throws Exception{
  6. UpdateRequest request = new UpdateRequest();
  7. request.index( "user").id( "1008");
  8. request.doc(XContentType.JSON, "name", "母夜叉");
  9. //插入数据
  10. UpdateResponse response = esClient.update(request, RequestOptions.DEFAULT);
  11. System.out.println(response.getResult());
  12. }

3.3  删除文档


  
  1. /**
  2. * 删除
  3. * @throws Exception
  4. */
  5. public static void delete () throws Exception{
  6. DeleteRequest request = new DeleteRequest();
  7. request.index( "user").id( "1008");
  8. //插入数据
  9. DeleteResponse delete = esClient.delete(request, RequestOptions.DEFAULT);
  10. System.out.println(delete.getResult());
  11. }

 3.4  批量添加文档

有些情况下,单条插入效率太低,可以使用es的批量插入功能一次性添加多条数据


  
  1. /**
  2. * 批量添加
  3. * @throws Exception
  4. */
  5. public static void batchInsert () throws Exception{
  6. BulkRequest bulkRequest = new BulkRequest();
  7. User user1 = new User( "关羽", "男", 33, 5500);
  8. String userData1 = objectMapper.writeValueAsString(user1);
  9. IndexRequest indexRequest1 = new IndexRequest().index( "user").id( "1002").source(userData1, XContentType.JSON);
  10. bulkRequest.add(indexRequest1);
  11. User user2 = new User( "黄忠", "男", 50, 8000);
  12. String userData2 = objectMapper.writeValueAsString(user2);
  13. IndexRequest indexRequest2 = new IndexRequest().index( "user").id( "1003").source(userData2, XContentType.JSON);
  14. bulkRequest.add(indexRequest2);
  15. User user3 = new User( "黄忠2", "男", 49, 10000);
  16. String userData3 = objectMapper.writeValueAsString(user3);
  17. IndexRequest indexRequest3 = new IndexRequest().index( "user").id( "1004").source(userData3, XContentType.JSON);
  18. bulkRequest.add(indexRequest3);
  19. User user4 = new User( "赵云", "男", 33, 12000);
  20. String userData4 = objectMapper.writeValueAsString(user4);
  21. IndexRequest indexRequest4 = new IndexRequest().index( "user").id( "1005").source(userData4, XContentType.JSON);
  22. bulkRequest.add(indexRequest4);
  23. User user5 = new User( "马超", "男", 38, 20000);
  24. String userData5 = objectMapper.writeValueAsString(user5);
  25. IndexRequest indexRequest5 = new IndexRequest().index( "user").id( "1006").source(userData5, XContentType.JSON);
  26. bulkRequest.add(indexRequest5);
  27. User user6 = new User( "关羽", "男", 41, 27000);
  28. String userData6 = objectMapper.writeValueAsString(user6);
  29. IndexRequest indexRequest6 = new IndexRequest().index( "user").id( "1007").source(userData6, XContentType.JSON);
  30. bulkRequest.add(indexRequest6);
  31. BulkResponse bulkResponse = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
  32. System.out.println(bulkResponse.status());
  33. System.out.println(bulkResponse.getItems());
  34. }

 

3.5  批量删除

可以通过批量操作一次性删除多条数据


  
  1. /**
  2. * 批量删除
  3. * @throws Exception
  4. */
  5. public static void batchDelete () throws Exception{
  6. BulkRequest bulkRequest = new BulkRequest();
  7. DeleteRequest indexRequest1 = new DeleteRequest().index( "user").id( "1002");
  8. DeleteRequest indexRequest2 = new DeleteRequest().index( "user").id( "1003");
  9. DeleteRequest indexRequest3 = new DeleteRequest().index( "user").id( "1004");
  10. DeleteRequest indexRequest4 = new DeleteRequest().index( "user").id( "1005");
  11. DeleteRequest indexRequest5 = new DeleteRequest().index( "user").id( "1006");
  12. DeleteRequest indexRequest6 = new DeleteRequest().index( "user").id( "1007");
  13. bulkRequest.add(indexRequest1);
  14. bulkRequest.add(indexRequest2);
  15. bulkRequest.add(indexRequest3);
  16. bulkRequest.add(indexRequest4);
  17. bulkRequest.add(indexRequest5);
  18. bulkRequest.add(indexRequest6);
  19. BulkResponse bulkResponse = esClient.bulk(bulkRequest, RequestOptions.DEFAULT);
  20. System.out.println(bulkResponse.status());
  21. System.out.println(bulkResponse.getItems());
  22. }

 4、文档搜索相关api的使用

我们知道es最强大的功能就是文档检索了,接下来演示下与es文档查询相关的常用API的操作;

4.1  查询某个索引下的所有数据


  
  1. /**
  2. * 查询某个索引下的所有数据
  3. * @throws Exception
  4. */
  5. public static void searchIndexAll () throws Exception{
  6. SearchRequest request = new SearchRequest();
  7. request.indices( "user");
  8. // 索引中的全部数据查询
  9. SearchSourceBuilder query = new SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
  10. request.source(query);
  11. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  12. SearchHits hits = response.getHits();
  13. for (SearchHit searchHit : hits){
  14. System.out.println(searchHit.getSourceAsString());
  15. }
  16. }

执行一下对该方法的调用

这个效果和在kibana中下面的操作效果是一样的

4.2  批量查询多条数据

针对那种需要一次性查出多条数据的场景可以考虑使用


  
  1. MultiGetRequest multiGetRequest = new MultiGetRequest();
  2. multiGetRequest.add( "user", "1002");
  3. multiGetRequest.add( "user", "1003");
  4. MultiGetResponse responses = esClient
  5. .mget(multiGetRequest, RequestOptions.DEFAULT);
  6. Iterator<MultiGetItemResponse> iterator = responses.iterator();
  7. while (iterator.hasNext()){
  8. MultiGetItemResponse next = iterator.next();
  9. System.out.println(next.getResponse().getSourceAsString());
  10. }

4.3  根据条件精准查询

根据性别查询,有点类似于mysql 中的 where sex='女' 这样的效果


  
  1. TermQueryBuilder ageQueryBuilder = QueryBuilders.termQuery( "sex", "女");
  2. SearchSourceBuilder query = new SearchSourceBuilder().query(ageQueryBuilder);
  3. request.source(query);
  4. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  5. System.out.println(response.getHits().getHits());
  6. System.out.println(response.getHits().getTotalHits());
  7. SearchHits hits = response.getHits();
  8. for (SearchHit searchHit : hits){
  9. System.out.println(searchHit.getSourceAsString());
  10. }

4.4  分页查询

考察from + size的使用


  
  1. SearchSourceBuilder sourceBuilder = new
  2. SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
  3. sourceBuilder.from( 0).size( 3);
  4. request.source(sourceBuilder);
  5. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  6. System.out.println(response.getHits().getHits());
  7. System.out.println(response.getHits().getTotalHits());
  8. SearchHits hits = response.getHits();
  9. for (SearchHit searchHit : hits){
  10. System.out.println(searchHit.getSourceAsString());
  11. }

4.5  查询结果按照某个字段进行排序

将查询结果按照age进行排序


  
  1. SearchSourceBuilder sourceBuilder = new
  2. SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
  3. sourceBuilder.sort( "age",SortOrder.ASC);
  4. request.source(sourceBuilder);
  5. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  6. System.out.println(response.getHits().getHits());
  7. System.out.println(response.getHits().getTotalHits());
  8. SearchHits hits = response.getHits();
  9. for (SearchHit searchHit : hits){
  10. System.out.println(searchHit.getSourceAsString());
  11. }

4.6  查询结果过滤某些字段

类似于mysql中只查询某个表的部分字段


  
  1. SearchSourceBuilder sourceBuilder = new
  2. SearchSourceBuilder().query(QueryBuilders.matchAllQuery());
  3. request.source(sourceBuilder);
  4. String[] includes = { "name", "sex"};
  5. String[] excludes = { "age"};
  6. sourceBuilder.fetchSource(includes,excludes);
  7. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  8. System.out.println(response.getHits().getHits());
  9. System.out.println(response.getHits().getTotalHits());
  10. SearchHits hits = response.getHits();
  11. for (SearchHit searchHit : hits){
  12. System.out.println(searchHit.getSourceAsString());
  13. }

4.7  多条件查询

es可以像mysql那样组合多个条件进行查询,考察对BoolQuery的使用,如下:查询性别为难男,年龄在35到45之间的用户;


  
  1. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  2. boolQueryBuilder.must(QueryBuilders.matchQuery( "sex", "男"));
  3. boolQueryBuilder.must(QueryBuilders.rangeQuery( "age").lt( 45).gt( 35));
  4. sourceBuilder.query(boolQueryBuilder);
  5. request.source(sourceBuilder);
  6. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  7. System.out.println(response.getHits().getHits());
  8. System.out.println(response.getHits().getTotalHits());
  9. SearchHits hits = response.getHits();
  10. for (SearchHit searchHit : hits){
  11. System.out.println(searchHit.getSourceAsString());
  12. }

4.8  范围查询


  
  1. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  2. RangeQueryBuilder rangeQueryBuilder =
  3. QueryBuilders.rangeQuery( "age").gte( 35).lte( 45);
  4. sourceBuilder.query(rangeQueryBuilder);
  5. request.source(sourceBuilder);
  6. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  7. System.out.println(response.getHits().getHits());
  8. System.out.println(response.getHits().getTotalHits());
  9. SearchHits hits = response.getHits();
  10. for (SearchHit searchHit : hits){
  11. System.out.println(searchHit.getSourceAsString());
  12. }

4.9  模糊查询


  
  1. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  2. FuzzyQueryBuilder fuzzyQueryBuilder =
  3. QueryBuilders.fuzzyQuery( "name", "黄忠")
  4. .fuzziness(Fuzziness.ONE);
  5. sourceBuilder.query(fuzzyQueryBuilder);
  6. request.source(sourceBuilder);
  7. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  8. System.out.println(response.getHits().getHits());
  9. System.out.println(response.getHits().getTotalHits());
  10. SearchHits hits = response.getHits();
  11. for (SearchHit searchHit : hits){
  12. System.out.println(searchHit.getSourceAsString());
  13. }

4.10   高亮查询


  
  1. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();
  2. TermQueryBuilder ageQueryBuilder = QueryBuilders.termQuery( "age", 33);
  3. HighlightBuilder highlightBuilder = new HighlightBuilder();
  4. highlightBuilder.preTags( "<font color='red'>");
  5. highlightBuilder.postTags( "</font>");
  6. highlightBuilder.field( "name");
  7. sourceBuilder.highlighter(highlightBuilder);
  8. sourceBuilder.query(ageQueryBuilder);
  9. request.source(sourceBuilder);
  10. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  11. System.out.println(response.getHits().getHits());
  12. System.out.println(response.getHits().getTotalHits());
  13. SearchHits hits = response.getHits();
  14. for (SearchHit searchHit : hits){
  15. System.out.println(searchHit.getSourceAsString());
  16. }

4.11  多字段查询multi_match

这个用法表示从多个字段中匹配某个关键字


  
  1. SearchSourceBuilder builder = new SearchSourceBuilder();
  2. MultiMatchQueryBuilder multiMatchQuery = QueryBuilders.multiMatchQuery( "黄忠", "name", "sex");
  3. multiMatchQuery.operator(Operator.OR);
  4. builder.query(multiMatchQuery);
  5. request.source(builder);
  6. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  7. System.out.println(response.getHits().getHits());
  8. System.out.println(response.getHits().getTotalHits());
  9. SearchHits hits = response.getHits();
  10. for (SearchHit searchHit : hits){
  11. System.out.println(searchHit.getSourceAsString());
  12. }

4.12  聚合查询


  
  1. SearchSourceBuilder builder = new SearchSourceBuilder();
  2. AggregationBuilder aggregationBuilder = AggregationBuilders.max( "maxAge").field( "age");
  3. builder.aggregation(aggregationBuilder);
  4. request.source(builder);
  5. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  6. System.out.println(response.getHits().getHits());
  7. System.out.println(response.getHits().getTotalHits());
  8. SearchHits hits = response.getHits();
  9. for (SearchHit searchHit : hits){
  10. System.out.println(searchHit.getSourceAsString());
  11. }

4.13  分组查询


  
  1. SearchSourceBuilder builder = new SearchSourceBuilder();
  2. AggregationBuilder aggregationBuilder = AggregationBuilders.terms( "ageGroup").field( "age");
  3. builder.aggregation(aggregationBuilder);
  4. request.source(builder);
  5. SearchResponse response = esClient.search(request, RequestOptions.DEFAULT);
  6. System.out.println(response.getHits().getHits());
  7. System.out.println(response.getHits().getTotalHits());
  8. SearchHits hits = response.getHits();
  9. for (SearchHit searchHit : hits){
  10. System.out.println(searchHit.getSourceAsString());
  11. }

四、与springboot 整合

es提供了与spring,springboot快速整合的第三方SDK,接下来以spring-data为例进行说明;

spring-boot-starter-data-elasticsearch 与spring其他相关的jpa方式使用类似,封装了丰富的API接口,客户只需要继承其提供的接口,就能方便的使用内置的API

前置准备

本地创建一个maven工程

1、导入核心依赖


  
  1. <parent>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-parent</artifactId>
  4. <version> 2.3 .6.RELEASE</version>
  5. <relativePath/>
  6. </parent>
  7. <dependencies>
  8. <dependency>
  9. <groupId>org.projectlombok</groupId>
  10. <artifactId>lombok</artifactId>
  11. </dependency>
  12. <dependency>
  13. <groupId>org.springframework.boot</groupId>
  14. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  15. </dependency>
  16. <dependency>
  17. <groupId>org.springframework.boot</groupId>
  18. <artifactId>spring-boot-devtools</artifactId>
  19. <scope>runtime</scope>
  20. <optional> true</optional>
  21. </dependency>
  22. <dependency>
  23. <groupId>org.springframework.boot</groupId>
  24. <artifactId>spring-boot-starter-test</artifactId>
  25. <scope>test</scope>
  26. </dependency>
  27. <dependency>
  28. <groupId>org.springframework.boot</groupId>
  29. <artifactId>spring-boot-test</artifactId>
  30. </dependency>
  31. <dependency>
  32. <groupId>junit</groupId>
  33. <artifactId>junit</artifactId>
  34. </dependency>
  35. <dependency>
  36. <groupId>org.springframework</groupId>
  37. <artifactId>spring-test</artifactId>
  38. </dependency>
  39. </dependencies>

2、核心配置文件


  
  1. # es 服务地址
  2. elasticsearch.host=IP
  3. # es 服务端口
  4. elasticsearch.port= 9200
  5. # 配置日志级别,开启 debug 日志
  6. logging.level.com.congge=debug

整合过程

1、创建一个实体类

该实体类属于连接es文档与客户端的一个中间转换层,使用过jpa或者mybatis-plus的同学对这个应该不陌生;


  
  1. import lombok.AllArgsConstructor;
  2. import lombok.Data;
  3. import lombok.NoArgsConstructor;
  4. import lombok.ToString;
  5. import org.springframework.data.annotation.Id;
  6. import org.springframework.data.elasticsearch.annotations.Document;
  7. import org.springframework.data.elasticsearch.annotations.Field;
  8. import org.springframework.data.elasticsearch.annotations.FieldType;
  9. @Data
  10. @NoArgsConstructor
  11. @AllArgsConstructor
  12. @ToString
  13. @Document(indexName = "shopping", shards = 3, replicas = 1)
  14. public class Product {
  15. //必须有 id,这里的 id 是全局唯一的标识,等同于 es 中的"_id"
  16. @Id
  17. private Long id; //商品唯一标识
  18. /**
  19. * type : 字段数据类型
  20. * analyzer : 分词器类型
  21. * index : 是否索引(默认:true)
  22. * Keyword : 短语,不进行分词
  23. */
  24. @Field(type = FieldType.Text, analyzer = "ik_max_word")
  25. private String title; //商品名称
  26. @Field(type = FieldType.Keyword)
  27. private String category; //分类名称
  28. @Field(type = FieldType.Double)
  29. private Double price; //商品价格
  30. @Field(type = FieldType.Keyword, index = false)
  31. private String images; //图片地址
  32. }

2、提供一个接口,继承ElasticsearchRepository


  
  1. import com.congge.entity.Product;
  2. import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
  3. import org.springframework.stereotype.Repository;
  4. @Repository
  5. public interface ProductDao extends ElasticsearchRepository<Product, Long>{
  6. }

3、核心配置类


  
  1. import lombok.Data;
  2. import org.apache.http.HttpHost;
  3. import org.elasticsearch.client.RestClient;
  4. import org.elasticsearch.client.RestClientBuilder;
  5. import org.elasticsearch.client.RestHighLevelClient;
  6. import org.springframework.boot.context.properties.ConfigurationProperties;
  7. import org.springframework.context.annotation.Configuration;
  8. //import org.springframework.data.elasticsearch.config.AbstractElasticsearchConfiguration;
  9. @ConfigurationProperties(prefix = "elasticsearch")
  10. @Configuration
  11. @Data
  12. public class EsConfig extends com.congge.config.AbstractElasticsearchConfiguration {
  13. private String host ;
  14. private Integer port ;
  15. //重写父类方法
  16. @Override
  17. public RestHighLevelClient elasticsearchClient () {
  18. RestClientBuilder builder = RestClient.builder( new HttpHost(host, port));
  19. RestHighLevelClient restHighLevelClient = new
  20. RestHighLevelClient(builder);
  21. return restHighLevelClient;
  22. }
  23. }

  
  1. import org.elasticsearch.client.RestHighLevelClient;
  2. import org.springframework.context.annotation.Bean;
  3. import org.springframework.data.elasticsearch.config.ElasticsearchConfigurationSupport;
  4. import org.springframework.data.elasticsearch.core.ElasticsearchOperations;
  5. import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
  6. import org.springframework.data.elasticsearch.core.convert.ElasticsearchConverter;
  7. public abstract class AbstractElasticsearchConfiguration extends ElasticsearchConfigurationSupport {
  8. //需重写本方法
  9. public abstract RestHighLevelClient elasticsearchClient ();
  10. @Bean(name = { "elasticsearchOperations", "elasticsearchTemplate" })
  11. public ElasticsearchOperations elasticsearchOperations (ElasticsearchConverter elasticsearchConverter) {
  12. return new ElasticsearchRestTemplate(elasticsearchClient(), elasticsearchConverter);
  13. }
  14. }

模拟测试

接下来通过junit的方式进行测试

1、索引相关的操作测试


  
  1. import com.congge.entity.Product;
  2. import org.junit.Test;
  3. import org.junit.runner.RunWith;
  4. import org.springframework.beans.factory.annotation.Autowired;
  5. import org.springframework.boot.test.context.SpringBootTest;
  6. import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
  7. import org.springframework.test.context.junit4.SpringRunner;
  8. @RunWith(SpringRunner.class)
  9. @SpringBootTest
  10. public class EsIndexTest {
  11. //注入 ElasticsearchRestTemplate
  12. @Autowired
  13. private ElasticsearchRestTemplate elasticsearchRestTemplate;
  14. //创建索引并增加映射配置
  15. @Test
  16. public void createIndex (){
  17. //创建索引,系统初始化会自动创建索引
  18. System.out.println( "创建索引");
  19. }
  20. @Test
  21. public void deleteIndex (){
  22. //创建索引,系统初始化会自动创建索引
  23. boolean flg = elasticsearchRestTemplate.deleteIndex(Product.class);
  24. System.out.println( "删除索引 = " + flg);
  25. }
  26. }

基于spring-data的方式,在工程启动的时候,会自动读取实体类相关的注解,自动完成索引的创建,运行下创建索引的测试方法;

然后去到kibana上面确认下是否创建成功;

2、文档相关的操作测试

该测试类中列举了常用的增删改查操作


  
  1. import com.congge.dao.ProductDao;
  2. import com.congge.entity.Product;
  3. import org.elasticsearch.index.query.QueryBuilders;
  4. import org.elasticsearch.index.query.TermQueryBuilder;
  5. import org.junit.Test;
  6. import org.junit.runner.RunWith;
  7. import org.springframework.beans.factory.annotation.Autowired;
  8. import org.springframework.boot.test.context.SpringBootTest;
  9. import org.springframework.data.domain.Page;
  10. import org.springframework.data.domain.PageRequest;
  11. import org.springframework.data.domain.Sort;
  12. import org.springframework.test.context.junit4.SpringRunner;
  13. import java.util.ArrayList;
  14. import java.util.List;
  15. @RunWith(SpringRunner.class)
  16. @SpringBootTest
  17. public class EsDocTest {
  18. @Autowired
  19. private ProductDao productDao;
  20. /**
  21. * 新增
  22. */
  23. @Test
  24. public void save () {
  25. Product product = new Product();
  26. product.setId( 2L);
  27. product.setTitle( "ipad mini");
  28. product.setCategory( "ipad");
  29. product.setPrice( 1998.0);
  30. product.setImages( "http://ipad.jpg");
  31. productDao.save(product);
  32. }
  33. //修改
  34. @Test
  35. public void update (){
  36. Product product = new Product();
  37. product.setId( 2L);
  38. product.setTitle( "iphone");
  39. product.setCategory( "mobile");
  40. product.setPrice( 6999.0);
  41. product.setImages( "http://www.phone.jpg");
  42. productDao.save(product);
  43. }
  44. //根据 id 查询
  45. @Test
  46. public void findById (){
  47. Product product = productDao.findById( 2L).get();
  48. System.out.println(product);
  49. }
  50. //查询所有
  51. @Test
  52. public void findAll (){
  53. Iterable<Product> products = productDao.findAll();
  54. for (Product product : products) {
  55. System.out.println(product);
  56. }
  57. }
  58. //删除
  59. @Test
  60. public void delete (){
  61. Product product = new Product();
  62. product.setId( 2L);
  63. productDao.delete(product);
  64. }
  65. //批量新增
  66. @Test
  67. public void saveAll (){
  68. List<Product> productList = new ArrayList<>();
  69. for ( int i = 0; i < 10; i++) {
  70. Product product = new Product();
  71. product.setId(Long.valueOf(i));
  72. product.setTitle( "iphone" + i);
  73. product.setCategory( "mobile");
  74. product.setPrice( 5999.0 + i);
  75. product.setImages( "http://www.phone.jpg");
  76. productList.add(product);
  77. }
  78. productDao.saveAll(productList);
  79. }
  80. //分页查询
  81. @Test
  82. public void findByPageable (){
  83. //设置排序(排序方式,正序还是倒序,排序的 id)
  84. Sort sort = Sort.by(Sort.Direction.DESC, "id");
  85. int currentPage= 0; //当前页,第一页从 0 开始, 1 表示第二页
  86. int pageSize = 5; //每页显示多少条
  87. //设置查询分页
  88. PageRequest pageRequest = PageRequest.of(currentPage, pageSize,sort);
  89. //分页查询
  90. Page<Product> productPage = productDao.findAll(pageRequest);
  91. for (Product Product : productPage.getContent()) {
  92. System.out.println(Product);
  93. }
  94. }
  95. /**
  96. * term 查询
  97. * search(termQueryBuilder) 调用搜索方法,参数查询构建器对象
  98. */
  99. @Test
  100. public void termQuery (){
  101. TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery( "title", "iphone");
  102. Iterable<Product> products = productDao.search(termQueryBuilder);
  103. for (Product product : products) {
  104. System.out.println(product);
  105. }
  106. }
  107. /**
  108. * term 查询加分页
  109. */
  110. @Test
  111. public void termQueryByPage (){
  112. int currentPage= 0 ;
  113. int pageSize = 5;
  114. //设置查询分页
  115. PageRequest pageRequest = PageRequest.of(currentPage, pageSize);
  116. TermQueryBuilder termQueryBuilder = QueryBuilders.termQuery( "title", "phone");
  117. Iterable<Product> products =
  118. productDao.search(termQueryBuilder,pageRequest);
  119. for (Product product : products) {
  120. System.out.println(product);
  121. }
  122. }
  123. }

测试其中批量新增的方法

更多丰富的API接口的使用有兴趣的同学可以基于此继续深入的研究学习。


转载:https://blog.csdn.net/congge_study/article/details/128194887
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场