• spring-boot操作elasticsearch


    一、环境准备

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

    1.1导入依赖

    1. <dependencies>
    2. <dependency>
    3. <groupId>org.springframework.bootgroupId>
    4. <artifactId>spring-boot-starter-data-elasticsearchartifactId>
    5. <version>2.7.18version>
    6. dependency>
    7. <dependency>
    8. <groupId>jakarta.jsongroupId>
    9. <artifactId>jakarta.json-apiartifactId>
    10. <version>2.0.1version>
    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 {
    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 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 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 hits = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), Employee.class);
    8. Employee p1 = hits.stream().findFirst().get().getContent();
    9. List> 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

    2.5进行文本高亮

    可以使用HighlightBuilder 类来设置查询结果文本高亮

    1. @Test
    2. public void testHighlight() {
    3. String PRE_TAG = "";
    4. String POST_TAG = "";
    5. HighlightBuilder.Field titleField = new HighlightBuilder.Field("name");
    6. titleField.preTags(PRE_TAG);
    7. titleField.postTags(POST_TAG);
    8. NativeSearchQueryBuilder nativeSearchQueryBuilder = new NativeSearchQueryBuilder();
    9. BoolQueryBuilder boolQueryBuilder = QueryBuilders.boolQuery();
    10. boolQueryBuilder.must(QueryBuilders.matchQuery("name", "李"));
    11. nativeSearchQueryBuilder.withQuery(boolQueryBuilder);
    12. nativeSearchQueryBuilder.withHighlightFields(titleField);
    13. SearchHits search = elasticsearchRestTemplate.search(nativeSearchQueryBuilder.build(), Employee.class);
    14. Map> files = search.getSearchHits().stream().findFirst().get().getHighlightFields();
    15. Assert.assertFalse(CollectionUtils.isEmpty(files));
    16. }

  • 相关阅读:
    交换机和路由器技术-26-OSPF末梢区域配置
    【Java|golang】791. 自定义字符串排序---使用桶排序
    「优选算法刷题」:比较含退格的字符串
    计算机毕业设计 基于SSM+Vue的农业信息管理系统的设计与实现 Java实战项目 附源码+文档+视频讲解
    MybatisPLUS,根据时间作为条件进行查询
    数据库和表的基本操作
    Delete `␍`eslint(prettier/prettier)黄色报错
    Qt中的数据库使用
    lvs(Linux virual server)
    Azure DevOps (三) 实现和Jenkins的联动
  • 原文地址:https://blog.csdn.net/littleschemer/article/details/136657798