SpringBoot整合ElasticSearch实现模糊查询,批量CRUD,排序,分页,高亮

男娘i 2023-10-11 20:41 81阅读 0赞

上一章:《ElasticSearch相关概念》


文章目录

    • 4.1 导入elasticsearch依赖
    • 4.2 创建高级客户端
    • 4.3 基本用法
      • 1.创建、判断存在、删除索引
      • 2.对文档的CRUD
      • 3.批量新增文档数据
      • 4.查询所有、模糊查询、分页查询、排序、高亮显示
    • 4.4 总结
      • 1.大致流程
      • 2.注意事项

上述部分为理论部分,本章跟着我一起来看一下具体开发中es是如何使用的

本章的完整代码在文末可以自行查看下载

4.1 导入elasticsearch依赖

在pom.xml里加入如下依赖:

  1. <dependency>
  2. <groupId>org.springframework.boot</groupId>
  3. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  4. </dependency>

我的SpringBoot版本:2.6.2
引入之后记得要看一下你的依赖版本是否和es的版本是否适配,如果不一致,会连接失败
在这里插入图片描述

启动es,在浏览器输入http://localhost:9200/查看es版本
在这里插入图片描述

很明显,我们的版本是不兼容的,我找了半天spring-boot-starter-data-elasticsearch依赖包也没找到适配es 8.6.1的依赖,为了不影响进度,我先退而求其次,先使用7.15.2这个版本的es

安装包:https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.15.2-windows-x86_64.zip

安装过程和我们第二章的过程一样,详情可参考:《第二章:ElasticSearch安装》

安装之后,我们可以看到我们的版本号已经变为7.15.2啦
在这里插入图片描述

4.2 创建高级客户端

  1. import org.apache.http.HttpHost;
  2. import org.elasticsearch.client.RestClient;
  3. import org.elasticsearch.client.RestHighLevelClient;
  4. import org.springframework.context.annotation.Bean;
  5. import org.springframework.context.annotation.Configuration;
  6. @Configuration
  7. public class ElasticSearchClientConfig {
  8. @Bean
  9. public RestHighLevelClient restHighLevelClient() {
  10. RestHighLevelClient client = new RestHighLevelClient(
  11. RestClient.builder(
  12. new HttpHost("127.0.0.1", 9200, "http")));
  13. return client;
  14. }
  15. }

如果你的es是部署在服务器上,那么127.0.0.1则需要改成你服务器的ip地址

4.3 基本用法

1.创建、判断存在、删除索引

  • 创建索引

    @Autowired

    1. private RestHighLevelClient restHighLevelClient;
    2. /**
    3. * 创建索引
    4. *
    5. * @return
    6. * @throws IOException
    7. */
    8. @GetMapping("/index/createIndex")
    9. public Object createIndex() throws IOException {
    10. //1.创建索引请求
    11. CreateIndexRequest request = new CreateIndexRequest("ninesunindex");
    12. //2.客户端执行请求IndicesClient,执行create方法创建索引,请求后获得响应
    13. CreateIndexResponse response =
    14. restHighLevelClient.indices().create(request, RequestOptions.DEFAULT);
    15. return response;
    16. }

在这里插入图片描述

可以看到索引已经创建成功

PS:如果不知道索引以及我们后面提到的名次概念,可以花几分钟读一下:《第三章:ElasticSearch相关概念》

  • 查询索引

    /**

    1. * 查询索引
    2. *
    3. * @return
    4. * @throws IOException
    5. */
    6. @GetMapping("/index/searchIndex")
    7. public Object searchIndex() throws IOException {
    8. //1.查询索引请求
    9. GetIndexRequest request = new GetIndexRequest("ninesunindex");
    10. //2.执行exists方法判断是否存在
    11. boolean exists = restHighLevelClient.indices().exists(request, RequestOptions.DEFAULT);
    12. return exists;
    13. }
  • 删除索引

    /**

    1. * 删除索引
    2. *
    3. * @return
    4. * @throws IOException
    5. */
    6. @GetMapping("/index/delIndex")
    7. public Object delIndex() throws IOException {
    8. //1.删除索引请求
    9. DeleteIndexRequest request = new DeleteIndexRequest("ninesunindex");
    10. //执行delete方法删除指定索引
    11. AcknowledgedResponse delete = restHighLevelClient.indices().delete(request, RequestOptions.DEFAULT);
    12. return delete.isAcknowledged();
    13. }

2.对文档的CRUD

创建文档:

注意:如果添加时不指定文档ID,他就会随机生成一个ID,ID唯一。

创建文档时若该ID已存在,发送创建文档请求后会更新文档中的数据

  • 新增文档

    /**

    1. * 新增文档
    2. *
    3. * @return
    4. * @throws IOException
    5. */
    6. @GetMapping("/document/add")
    7. public Object add() throws IOException {
    8. //1.创建对象
    9. User user = new User("Go", 21, new String[]{
    10. "内卷", "吃饭"});
    11. //2.创建请求
    12. IndexRequest request = new IndexRequest("ninesunindex");
    13. //3.设置规则 PUT /ljx666/_doc/1
    14. //设置文档id=6,设置超时=1s等,不设置会使用默认的
    15. //同时支持链式编程如 request.id("6").timeout("1s");
    16. request.id("6");
    17. request.timeout("1s");
    18. //4.将数据放入请求,要将对象转化为json格式
    19. //XContentType.JSON,告诉它传的数据是JSON类型
    20. request.source(JSONValue.toJSONString(user), XContentType.JSON);
    21. //5.客户端发送请求,获取响应结果
    22. IndexResponse indexResponse = restHighLevelClient.index(request, RequestOptions.DEFAULT);
    23. System.out.println(indexResponse.toString());
    24. System.out.println(indexResponse.status());
    25. return indexResponse;
    26. }
  • 获取文档中的数据

    /**

    1. * 获取文档中的数据
    2. *
    3. * @return
    4. * @throws IOException
    5. */
    6. @GetMapping("/document/get")
    7. public Object get() throws IOException {
    8. //1.创建请求,指定索引、文档id
    9. GetRequest request = new GetRequest("ninesunindex", "6");
    10. GetResponse getResponse = restHighLevelClient.get(request, RequestOptions.DEFAULT);
    11. System.out.println(getResponse);//获取响应结果
    12. //getResponse.getSource() 返回的是Map集合
    13. System.out.println(getResponse.getSourceAsString());//获取响应结果source中内容,转化为字符串
    14. return getResponse;
    15. }
  • 更新文档数据

注意:需要将User对象中的属性全部指定值,不然会被设置为空,如User只设置了名称,那么只有名称会被修改成功,其他会被修改为null。

  1. /**
  2. * 更新文档数据
  3. *
  4. * @return
  5. * @throws IOException
  6. */
  7. @GetMapping("/document/update")
  8. public Object update() throws IOException {
  9. //1.创建请求,指定索引、文档id
  10. UpdateRequest request = new UpdateRequest("ninesunindex", "6");
  11. User user = new User("GoGo", 21, new String[]{
  12. "内卷", "吃饭"});
  13. //将创建的对象放入文档中
  14. request.doc(JSONValue.toJSONString(user), XContentType.JSON);
  15. UpdateResponse updateResponse = restHighLevelClient.update(request, RequestOptions.DEFAULT);
  16. System.out.println(updateResponse.status());//更新成功返回OK
  17. return updateResponse;
  18. }
  • 删除文档数据

    /**

    1. * 删除文档数据
    2. *
    3. * @return
    4. * @throws IOException
    5. */
    6. @GetMapping("/document/delete")
    7. public Object delete() throws IOException {
    8. //1.创建删除文档请求
    9. DeleteRequest request = new DeleteRequest("ninesunindex", "6");
    10. DeleteResponse deleteResponse = restHighLevelClient.delete(request, RequestOptions.DEFAULT);
    11. System.out.println(deleteResponse.status());//更新成功返回OK
    12. return deleteResponse;
    13. }

3.批量新增文档数据

  • 批量新增文档数据

    /**

    1. * 批量新增文档数据
    2. *
    3. * @return
    4. * @throws IOException
    5. */
    6. @GetMapping("/document/addBatch")
    7. public Object addBatch() throws IOException {
    8. BulkRequest bulkRequest = new BulkRequest();
    9. //设置超时
    10. bulkRequest.timeout("10s");
    11. List<User> list = new ArrayList<>();
    12. list.add(new User("Java", 25, new String[]{
    13. "内卷"}));
    14. list.add(new User("Go", 18, new String[]{
    15. "内卷"}));
    16. list.add(new User("C", 30, new String[]{
    17. "内卷"}));
    18. list.add(new User("C++", 26, new String[]{
    19. "内卷"}));
    20. list.add(new User("Python", 20, new String[]{
    21. "内卷"}));
    22. int id = 1;
    23. //批量处理请求
    24. for (User u : list) {
    25. //不设置id会生成随机id
    26. bulkRequest.add(new IndexRequest("ninesunindex")
    27. .id("" + (id++))
    28. .source(JSONValue.toJSONString(u), XContentType.JSON));
    29. }
    30. BulkResponse bulkResponse = restHighLevelClient.bulk(bulkRequest, RequestOptions.DEFAULT);
    31. System.out.println(bulkResponse.hasFailures());//是否执行失败,false为执行成功
    32. return bulkResponse;
    33. }

4.查询所有、模糊查询、分页查询、排序、高亮显示

  1. @GetMapping("test")
  2. public Object test() throws IOException {
  3. SearchRequest searchRequest = new SearchRequest("ninesunindex");//里面可以放多个索引
  4. SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();//构造搜索条件
  5. //此处可以使用QueryBuilders工具类中的方法
  6. //1.查询所有
  7. sourceBuilder.query(QueryBuilders.matchAllQuery());
  8. //2.查询name中含有Java的
  9. sourceBuilder.query(QueryBuilders.multiMatchQuery("java", "userName"));
  10. //3.分页查询
  11. sourceBuilder.from(0).size(5);
  12. //4.按照score正序排列
  13. sourceBuilder.sort(SortBuilders.scoreSort().order(SortOrder.ASC));
  14. //5.按照id倒序排列(score会失效返回NaN)
  15. sourceBuilder.sort(SortBuilders.fieldSort("_id").order(SortOrder.DESC));
  16. //6.给指定字段加上指定高亮样式
  17. HighlightBuilder highlightBuilder = new HighlightBuilder();
  18. highlightBuilder.field("userName").preTags("<span style='color:red;'>").postTags("</span>");
  19. sourceBuilder.highlighter(highlightBuilder);
  20. searchRequest.source(sourceBuilder);
  21. SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
  22. //获取总条数
  23. System.out.println(searchResponse.getHits().getTotalHits().value);
  24. //输出结果数据(如果不设置返回条数,大于10条默认只返回10条)
  25. SearchHit[] hits = searchResponse.getHits().getHits();
  26. for (SearchHit hit : hits) {
  27. System.out.println("分数:" + hit.getScore());
  28. Map<String, Object> source = hit.getSourceAsMap();
  29. System.out.println("index->" + hit.getIndex());
  30. System.out.println("id->" + hit.getId());
  31. for (Map.Entry<String, Object> s : source.entrySet()) {
  32. System.out.println(s.getKey() + "--" + s.getValue());
  33. }
  34. }
  35. return searchResponse;
  36. }

4.4 总结

1.大致流程

创建对应的请求 —> 设置请求(添加规则,添加数据等) —> 执行对应的方法(传入请求,默认请求选项)–> 接收响应结果(执行方法返回值)–> 输出响应结果中需要的数据(source,status等)

2.注意事项

如果不指定id,会自动生成一个随机id

正常情况下,不应该这样使用new IndexRequest(“indexName”),如果索引发生改变了,那么代码都需要修改,可以定义一个枚举类或者一个专门存放常量的类,将变量用final static等进行修饰,并指定索引值。其他地方引用该常量即可,需要修改也只需修改该类即可。

elasticsearch相关的东西,版本都必须一致,不然会报错

elasticsearch很消耗内存,建议在内存较大的服务器上运行elasticsearch,否则会因为内存不足导致elasticsearch自动killed


git地址:https://gitee.com/ninesuntec/es-better.git

PS:本章git上的代码如果有被注释掉的,只是为了防止和后面的章节不冲突,并无错误,大家自行解注查看即可

下一章:《ElasticSearchRepository和ElasticsearchRestTemplate的使用》

发表评论

表情:
评论列表 (有 0 条评论,81人围观)

还没有评论,来说两句吧...

相关阅读