飞道的博客

Spring Data Elasticsearch(java操作ELK)

274人阅读  评论(0)

一、环境搭建

(1)导入依赖

 

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.12.RELEASE</version>
</parent>

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
</dependencies>

(2)编辑配置文件

# 注意: 地址一定不要有末尾字符 '/'
# ElasticsearchRestTemplate客户端的配置
spring:
  elasticsearch:
    rest:
      uris: http://192.168.8.128:9200  # ES服务器所在位置。集群多节点地址用逗号分隔。默认http://localhost:9200
#  data: # ElasticsearchTemplate客户端配置。所有的方法API和ElasticsearchRestTemplate完全相同。
#    elasticsearch:
#      cluster-name: docker-cluster # ES集群的名称。已过期
#      cluster-nodes: 192.168.137.128:9300 # ES集群多节点地址。多个地址用逗号分隔。在7版本后已过期

(3)编辑实体类型


  
  1. /**
  2. * Document - 描述类型和索引的映射。
  3. * indexName - 索引名称
  4. * shards - 主分片数量。默认值 1。
  5. * replicas - 副本分片数量。默认值 1。
  6. */
  7. @Data
  8. @NoArgsConstructor
  9. @AllArgsConstructor
  10. @Document(indexName = "stu_index", shards = 1, replicas = 0)
  11. public class Student implements Serializable {
  12. /**
  13. * Field - 当前属性和索引中的字段映射规则。
  14. * name - 字段名称。默认和当前类型属性名一致。
  15. * type - 字段类型。默认使用FieldType.AUTO。自动识别。
  16. * analyzer - 分词器。所有的Text类型字段默认使用standard分词器。
  17. * index - 是否创建索引。默认值 true。
  18. * format - 如果字段类型是date日期类型。此属性必须配置,用于设置日期格式化规则,使用DateFormat类型中的常量定义。
  19. */
  20. @Id
  21. @Field(name = "id", type = FieldType.Keyword)
  22. private Long id;
  23. @Field(name = "name", type = FieldType.Text, analyzer = "ik_max_word")
  24. private String name;
  25. @Field(name = "gender", type = FieldType.Keyword)
  26. private String gender;
  27. @Field(name = "age", type = FieldType.Integer)
  28. private int age;
  29. @Field(name = "hobbies", type = FieldType.Text, analyzer = "ik_smart")
  30. private List<String> hobbies;
  31. @Field(name = "isMarried", type = FieldType.Boolean)
  32. private boolean isMarried;
  33. @Field(name = "books", type = FieldType.Text, analyzer = "ik_smart", index = false)
  34. private String[] books;
  35. @Field(name = "birth", type = FieldType.Date, format = DateFormat.basic_date_time)
  36. private Date birth;
  37. }

 二、使用

(1)创建索引


  
  1. @SpringBootTest
  2. public class TestDataES {
  3. /**
  4. * Spring Data Elasticsearch客户端类型 - ElasticsearchRestTemplate客户端对象,
  5. * 由spring-boot-starter-data-elasticsearch启动时,自动装配创建。
  6. * 要求:
  7. * 1. 当前应用中,必须有启动类型,才能自动装配创建。
  8. * 2. 创建客户端时,根据配置文件,实现服务器连接。默认连接的ES服务器集群是:http://localhost:9200
  9. */
  10. @Autowired
  11. private ElasticsearchRestTemplate restTemplate;
  12. /**
  13. * 创建索引
  14. */
  15. @Test
  16. public void testCreateIndex (){
  17. /*
  18. * 在spring data elasticsearch中,所有的索引相关操作都封装在一个操作对象 IndexOperations 中。
  19. * 基于一个实体类型的类对象,创建索引操作对象。实体类型中,有使用注解描述的索引和映射相关信息。可以做为索引的创建的设置。
  20. */
  21. IndexOperations indexOps = restTemplate.indexOps(Student.class);
  22. // 创建索引
  23. indexOps.create();
  24. }
  25. }

(2)设置映射


  
  1. /**
  2. * 设置映射
  3. * 在商业开发中,几乎不会使用框架创建索引或设置映射。因为这是架构或者管理员的工作。且不适合使用代码实现
  4. */
  5. @Test
  6. public void testCreateIndexAndPutMapping (){
  7. IndexOperations indexOps = restTemplate.indexOps(Student.class);
  8. // 设置映射
  9. indexOps.putMapping(indexOps.createMapping());
  10. }

(3)删除索引


  
  1. /**
  2. * 删除索引
  3. */
  4. @Test
  5. public void testDeleteIndex (){
  6. restTemplate.indexOps(Student.class).delete();
  7. }

(4)新增单一文档


  
  1. /**
  2. * 新增单一文档
  3. */
  4. @Test
  5. public void testAddDocument () throws Exception{
  6. // 创建要新增的实体对象。手工赋予主键,返回结果就是新增的数据对象。
  7. Student student = new Student();
  8. student.setId( 1L);
  9. student.setName( "张三");
  10. student.setGender( "男");
  11. student.setAge( 25);
  12. SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd");
  13. student.setBirth(sdf.parse( "1996-01-01"));
  14. student.setBooks( new String[]{ "Java面向对象思想", "Spring In Action"});
  15. student.setHobbies(Arrays.asList( "吃饭", "上班", "睡觉"));
  16. student.setMarried( true);
  17. // 保存数据到Elasticsearch
  18. student = restTemplate.save(student);
  19. System.out.println(student);
  20. System.out.println( "====================================================");
  21. // 自动生成主键,返回的结果中包含Elasticsearch生成的主键。
  22. student = new Student();
  23. student.setName( "李四");
  24. student.setGender( "男");
  25. student.setAge( 21);
  26. student.setBirth(sdf.parse( "2000-01-01"));
  27. student.setBooks( new String[]{ "火影忍者", "海贼王"});
  28. student.setHobbies(Arrays.asList( "玩游戏", "睡觉", "看动漫"));
  29. student.setMarried( false);
  30. student = restTemplate.save(student);
  31. System.out.println(student);
  32. }

(5)批量新增文档


  
  1. /**
  2. * 批量新增文档
  3. */
  4. @Test
  5. public void testBatchAdd () throws Exception {
  6. SimpleDateFormat sdf = new SimpleDateFormat( "yyyy-MM-dd");
  7. List<Student> list = new ArrayList<>();
  8. list.add( new Student( 2L, "郭德纲", "男", 48, Arrays.asList( "郭麒麟"), true, new String[]{ "德云逗笑社"}, sdf.parse( "1973-01-18")));
  9. list.add( new Student( 3L, "于谦", "男", 52, Arrays.asList( "郭麒麟", "抽烟", "喝酒", "烫头"), true, new String[]{ "德云逗笑社"}, sdf.parse( "1969-01-24")));
  10. restTemplate.save(list);
  11. System.out.println( "批量新增结束");
  12. }

(6)删除文档


  
  1. /**
  2. * 删除文档
  3. */
  4. @Test
  5. public void testDeleteDocument (){
  6. // 删除类型对应的索引中的指定主键数据,返回删除数据的主键。注意:Elasticsearch中的文档主键都是字符串类型的。
  7. String response = restTemplate.delete( "1", Student.class);
  8. System.out.println(response);
  9. }

(7)更新文档


  
  1. /**
  2. * 更新文档。
  3. * save方法,可以覆盖同主键数据。案例省略
  4. * update更新,部分更新
  5. */
  6. @Test
  7. public void testUpdate (){
  8. UpdateQuery query =
  9. UpdateQuery.builder( "2")
  10. .withDocument(Document.parse( "{\"hobbies\":[\"郭麒麟\", \"郭汾阳\"]}"))
  11. .build();
  12. UpdateResponse response =
  13. restTemplate.update(query, IndexCoordinates.of( "stu_index"));
  14. System.out.println(response.getResult());
  15. }

三、查询

(1)主键查询文档


  
  1. /**
  2. * 主键查询文档
  3. */
  4. @Test
  5. public void testGetById (){
  6. Student student = restTemplate.get( "3", Student.class);
  7. System.out.println(student);
  8. }

(2)全字段搜索


  
  1. /**
  2. * querystring 搜索。所有的搜索的套路一致。具体方法如下:
  3. * SearchHits search(Query query, Class<T> clazz);
  4. * 参数query - 具体的条件。是spring data elasticsearch框架封装的类型。
  5. * 一般使用构建器创建搜索条件。
  6. * NativeSearchQueryBuilder().build()
  7. * .withQuery(QueryBuilder) - 提供具体的条件。此方法的参数类型是QueryBuilder
  8. * 这个QueryBuilder类型由elasticsearch提供的java客户端jar包定义。
  9. * QueryBuilder对象,一般使用构建器创建,QueryBuilders
  10. * 参数clazz - 返回结果每个document封装的对象类型。
  11. * 返回return - 搜索的结果。是一个完整的搜索结果对象。包含总数据个数,当前搜索集合,是否超时等。
  12. *
  13. * SearchHits类型实现了Iterable接口,可迭代。容器中每个对象的类型是SearchHit。
  14. * SearchHit类型中包含一个完整的搜索对象,由元数据和源数据组成。
  15. */
  16. @Test
  17. public void testQuerystring (){
  18. QueryBuilder queryBuilder =
  19. QueryBuilders.queryStringQuery( "郭");
  20. Query query =
  21. new NativeSearchQueryBuilder()
  22. .withQuery(queryBuilder) // 提供具体的条件。
  23. .build();
  24. SearchHits<Student> hits =
  25. restTemplate.search(query, Student.class);
  26. System.out.println( "搜索结果数据个数是: " + hits.getTotalHits());
  27. for(SearchHit<Student> hit : hits){
  28. // 源数据,就是保存在Elasticsearch中的数据
  29. Student content = hit.getContent();
  30. System.out.println( "源数据:" + content);
  31. }
  32. }

(3)搜索全部


  
  1. /**
  2. * 搜索全部
  3. */
  4. @Test
  5. public void testMatchAll (){
  6. SearchHits<Student> hits = restTemplate.search(
  7. new NativeSearchQueryBuilder()
  8. .withQuery(QueryBuilders.matchAllQuery())
  9. .build(), Student.class);
  10. for(SearchHit<Student> hit : hits){
  11. System.out.println(hit.getContent());
  12. }
  13. }

(4)匹配搜索


  
  1. /**
  2. * match搜索
  3. */
  4. @Test
  5. public void testQueryByMatch (){
  6. SearchHits<Student> hits = restTemplate.search(
  7. new NativeSearchQueryBuilder()
  8. .withQuery(
  9. QueryBuilders.matchQuery(
  10. "name",
  11. "于谦")
  12. )
  13. .build(),
  14. Student.class
  15. );
  16. print(hits);
  17. }
  18. private void print (SearchHits<Student> hits){
  19. for(SearchHit<Student> hit : hits){
  20. System.out.println(hit.getContent());
  21. }
  22. }

(5)短语搜索


  
  1. /**
  2. * match phrase搜索
  3. */
  4. @Test
  5. public void testQueryByMatchPhrase (){
  6. SearchHits<Student> hits = restTemplate.search(
  7. new NativeSearchQueryBuilder()
  8. .withQuery(
  9. QueryBuilders.matchPhraseQuery(
  10. "hobbies",
  11. "烫头"
  12. )
  13. )
  14. .build(),
  15. Student.class
  16. );
  17. print(hits);
  18. }

(6)范围搜索


  
  1. /**
  2. * range搜索
  3. */
  4. @Test
  5. public void testQueryByRange (){
  6. SearchHits<Student> hits =
  7. restTemplate.search(
  8. new NativeSearchQueryBuilder()
  9. .withQuery(
  10. QueryBuilders.rangeQuery( "age")
  11. .lte( 35).gte( 30)
  12. )
  13. .build(),
  14. Student.class
  15. );
  16. print(hits);
  17. }

(7)范围搜索


  
  1. /**
  2. * bool搜索。多条件
  3. */
  4. @Test
  5. public void testQueryByBool (){
  6. /*
  7. * bool搜索条件中包含3个条件集合。List<QueryBuilder>,分别命名为must(必须匹配的条件),mustNot(必须不匹配的条件),should(任意匹配的条件)。
  8. * 每个条件集合管理方案都提供了两个方法API。以must举例如下:
  9. * must() - 获取must必要条件集合,返回List<QueryBuilder>。
  10. * must(QueryBuilder) - 把参数添加到must条件集合中,返回BoolQueryBuilder类型对象,即当前对象本身(this)。
  11. */
  12. BoolQueryBuilder queryBuilder =
  13. QueryBuilders.boolQuery();
  14. List<QueryBuilder> must = queryBuilder.must();
  15. must.add(QueryBuilders.matchQuery( "name", "郭"));
  16. queryBuilder.should(QueryBuilders.rangeQuery( "age").gt( 30))
  17. .should(QueryBuilders.rangeQuery( "age").lt( 60));
  18. // 搜索
  19. SearchHits<Student> hits =
  20. restTemplate.search(
  21. new NativeSearchQueryBuilder()
  22. .withQuery(queryBuilder)
  23. .build(),
  24. Student.class
  25. );
  26. print(hits);
  27. }

(8)分页和排序


  
  1. /**
  2. * 分页+排序
  3. * 在spring data系列框架中,分页和排序可以混合处理。使用通用定义spring data commons中的Page接口实现。应用接口的实现类型PageRequest处理。
  4. * PageRequest类型中,提供静态方法of(int page, int size[, Sort sort]);
  5. * page - 查询第几页,页码数字从0开始计数。
  6. * size - 查询多少行。
  7. * Sort - 具体的排序规则。可选参数。
  8. */
  9. @Test
  10. public void testQueryByPageAndSort (){
  11. SearchHits<Student> hits =
  12. restTemplate.search(
  13. new NativeSearchQueryBuilder()
  14. .withQuery(QueryBuilders.matchAllQuery())
  15. .withPageable(
  16. PageRequest.of( 0, 2,
  17. Sort.by(
  18. Sort.Order.desc( "age"),
  19. Sort.Order.asc( "id")
  20. )
  21. )
  22. )
  23. .build(),
  24. Student.class
  25. );
  26. print(hits);
  27. }

(9)高亮处理


  
  1. /**
  2. * 搜索结果高亮处理
  3. * 提供高亮字段,字段名,是否分段(每段几个字符,返回几段),前后缀。
  4. * 创建Query对象,做搜索处理。
  5. */
  6. @Test
  7. public void testQueryHighLight (){
  8. // 创建高亮字段,必须和具体的字段名绑定。
  9. HighlightBuilder. Field field1 = new HighlightBuilder.Field( "name");
  10. // 高亮前缀
  11. field1.preTags( "<span style='color: red'>");
  12. // 高亮后缀
  13. field1.postTags( "</span>");
  14. // 分段的每段字符数
  15. field1.fragmentSize(Integer.MAX_VALUE);
  16. // 分段后,返回几段
  17. field1.numOfFragments( 1);
  18. Query query =
  19. new NativeSearchQueryBuilder()
  20. .withQuery(
  21. QueryBuilders.matchQuery(
  22. "name",
  23. "于谦")
  24. )
  25. .withHighlightFields(field1)
  26. .build();
  27. SearchHits<Student> hits =
  28. restTemplate.search(query, Student.class);
  29. for (SearchHit<Student> hit : hits){
  30. // 获取源数据
  31. Student content = hit.getContent();
  32. // 找高亮数据
  33. List<String> hl = hit.getHighlightField( "name");
  34. // 判断是否有高亮数据
  35. if(hl != null && hl.size() > 0){
  36. // 有高亮数据
  37. (hl.get( 0));
  38. }
  39. System.out.println(content);
  40. }
  41. }


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