当前位置:   article > 正文

spring-boot操作elasticsearch

spring-boot操作elasticsearch

一、环境准备

springboot与elasticsearch的更新都非常快,为了避免兼容性问题,要注意下选择的版本问题。具体的可参考官网 -->  springboot与elasticsearch版本兼容性

1.1导入依赖

  1. <dependencies>
  2. <dependency>
  3. <groupId>org.springframework.boot</groupId>
  4. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  5. <version>2.7.18</version>
  6. </dependency>
  7. <dependency>
  8. <groupId>jakarta.json</groupId>
  9. <artifactId>jakarta.json-api</artifactId>
  10. <version>2.0.1</version>
  11. </dependency>
  12. </dependencies>

1.2application.properties文件配置

  1. spring.elasticsearch.rest.uris=http://localhost:9200
  2. spring.elasticsearch.rest.username=dev
  3. spring.elasticsearch.rest.password=123456

1.3创建实体对象

  1. import lombok.Data;
  2. import org.springframework.data.annotation.Id;
  3. import org.springframework.data.elasticsearch.annotations.Document;
  4. import org.springframework.data.elasticsearch.annotations.Field;
  5. import org.springframework.data.elasticsearch.annotations.FieldType;
  6. @Document(indexName = "employee")
  7. @Data
  8. public class Employee {
  9. @Id
  10. private int id;
  11. @Field(name = "name")
  12. private String name;
  13. @Field(name = "addr", type = FieldType.Keyword)
  14. private String addr;
  15. }

该实体类加上@Document注解之后,程序启动后就会自动向ED发送创建索引的请求(若没有则创建)。

1.4创建Repository接口

  1. import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
  2. public interface EmployeeRepository extends ElasticsearchRepository<Employee, Integer> {
  3. }

1.5Crud测试案例

使用该接口可方便对索引进行增删查改。例子比较简单,我们直接写个单元测试。代码如下:

  1. import gamecontext.admin.elasticsearch.Employee;
  2. import gamecontext.admin.elasticsearch.EmployeeRepository;
  3. import org.junit.Assert;
  4. import org.junit.Test;
  5. import org.junit.runner.RunWith;
  6. import org.springframework.beans.factory.annotation.Autowired;
  7. import org.springframework.boot.test.context.SpringBootTest;
  8. import org.springframework.test.context.junit4.SpringRunner;
  9. @SpringBootTest()
  10. @RunWith(SpringRunner.class)
  11. public class ElasticsearchTest {
  12. @Autowired
  13. private EmployeeRepository repository;
  14. @Test
  15. public void testSave() {
  16. Employee p = new Employee();
  17. p.setId(3);
  18. p.setAddr("北京");
  19. p.setName("Tim");
  20. repository.save(p);
  21. Assert.assertEquals("Tim", repository.findById(3).get().getName());
  22. }
  23. @Test
  24. public void testDelete() {
  25. Employee p = new Employee();
  26. p.setId(4);
  27. p.setAddr("北京");
  28. p.setName("Tim");
  29. repository.save(p);
  30. repository.deleteById(4);
  31. Assert.assertFalse(repository.findById(4).isPresent());
  32. }
  33. @Test
  34. public void testUpdate() {
  35. Employee p = repository.findById(3).get();
  36. p.setName("南京");
  37. repository.save(p);
  38. Assert.assertEquals(repository.findById(3).get().getName(), "南京");
  39. }
  40. }

二、使用QueryBuilder进行文档的复杂查询

ElasticsearchRepository只能对文档进行简单的增删查改,如果遇到复杂的全文搜索,则需要借助QueryBuilder和ElasticsearchRestTemplate相关API

2.1数据准备

往索引插入3条文档,数据如下

2.2进行must查询 

  1. import gamecontext.admin.elasticsearch.Employee;
  2. import gamecontext.admin.elasticsearch.EmployeeRepository;
  3. import org.elasticsearch.index.query.BoolQueryBuilder;
  4. import org.elasticsearch.index.query.QueryBuilders;
  5. import org.junit.Assert;
  6. import org.junit.Test;
  7. import org.junit.runner.RunWith;
  8. import org.springframework.beans.factory.annotation.Autowired;
  9. import org.springframework.boot.test.context.SpringBootTest;
  10. import org.springframework.data.elasticsearch.core.ElasticsearchRestTemplate;
  11. import org.springframework.data.elasticsearch.core.SearchHits;
  12. import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
  13. import org.springframework.test.context.junit4.SpringRunner;
  14. @SpringBootTest()
  15. @RunWith(SpringRunner.class)
  16. public class ElasticsearchTest2 {
  17. @Autowired
  18. private ElasticsearchRestTemplate elasticsearchRestTemplate;
  19. @Test
  20. public void testMust() {
  21. NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
  22. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
  23. boolQueryBuilder.must(QueryBuilders.matchQuery("name", "李"))
  24. .must(QueryBuilders.matchQuery("name", "四"));
  25. nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
  26. SearchHits<Employee> hits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), Employee.class);
  27. Assert.assertTrue(hits.stream().findFirst().isPresent());
  28. Assert.assertEquals(hits.stream().findFirst().get().getContent().getName(), "李四");
  29. }
  30. }

等效的Kibana命令

2.3进行range查询 

  1. @Test
  2. public void testRange() {
  3. NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
  4. RangeQueryBuilder builder = QueryBuilders.rangeQuery("age").lte(20).gte(10);
  5. nativeSearchQueryBuilder.withQuery(builder);
  6. SearchHits<Employee> hits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), Employee.class);
  7. Assert.assertEquals(2, hits.getTotalHits());
  8. }

等效的Kibana命令

2.4进行sort排序

  1. @Test
  2. public void testSort() {
  3. NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
  4. nativeSearchQueryBuilder.withQuery(QueryBuilders.matchAllQuery());
  5. nativeSearchQueryBuilder.withSort(SortBuilders.fieldSort("age").order(SortOrder.DESC));
  6. // .withSort(SortBuilders.fieldSort("name").order(SortOrder.ASC));
  7. SearchHits<Employee> hits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), Employee.class);
  8. Employee p1 = hits.stream().findFirst().get().getContent();
  9. List<SearchHit<Employee>> list = hits.stream().collect(Collectors.toUnmodifiableList());
  10. Assert.assertTrue(list.get(0).getContent().getAge()>list.get(1).getContent().getAge());
  11. Assert.assertTrue(list.get(1).getContent().getAge()>list.get(2).getContent().getAge());
  12. }

 等效的Kibana命令

默认情况下,text类型的字段是不能排序的,否则会报以下异常,

Caused by: ElasticsearchException[Elasticsearch exception [type=illegal_argument_exception, reason=Text fields are not optimised for operations that require per-document field data like aggregations and sorting, so these operations are disabled by default. Please use a keyword field instead. Alternatively, set fielddata=true on [name] in order to load field data by uninverting the inverted index. Note that this can use significant memory.]]

翻译如下:

默认情况下,文本字段禁用字段数据。在[region]上设置fielddata=true,以便通过取消反转索引将fielddata加载到内存中。请注意,这可能会占用大量内存。

解决方法:

  • 将name字段设置为keyword类型
  • 将name字段的fielddata()为true

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/很楠不爱3/article/detail/228571
推荐阅读
相关标签
  

闽ICP备14008679号