创建索引

在elasticsearch中创建students索引

  1. PUT /students
  2. {
  3. "settings": {
  4. "number_of_shards": 3,
  5. "number_of_replicas": 2,
  6. "index.max_ngram_diff":30,
  7. "analysis": {
  8. "analyzer": {
  9. "ngram_analyzer": {
  10. "tokenizer": "ngram_tokenizer"
  11. }
  12. },
  13. "tokenizer": {
  14. "ngram_tokenizer": {
  15. "type": "ngram",
  16. "min_gram": 1,
  17. "max_gram": 30,
  18. "token_chars": [
  19. "letter",
  20. "digit"
  21. ]
  22. }
  23. }
  24. }
  25. },
  26. "mappings": {
  27. "properties": {
  28. "id": {
  29. "type": "long"
  30. },
  31. "name": {
  32. "type": "text",
  33. "analyzer": "ngram_analyzer"
  34. },
  35. "gender": {
  36. "type": "keyword"
  37. },
  38. "birthDate": {
  39. "type": "date",
  40. "format": "yyyy-MM-dd"
  41. }
  42. }
  43. }
  44. }

创建项目

添加依赖

使用java操作Elasticsearce需要添加spring-boot-starter-data-elasticsearch依赖

  1. <?xml version="1.0" encoding="UTF-8"?>
  2. <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  3. xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
  4. <modelVersion>4.0.0</modelVersion>
  5. <parent>
  6. <groupId>org.springframework.boot</groupId>
  7. <artifactId>spring-boot-starter-parent</artifactId>
  8. <version>2.3.2.RELEASE</version>
  9. <relativePath/> <!-- lookup parent from repository -->
  10. </parent>
  11. <groupId>cn.tedu</groupId>
  12. <artifactId>Elasticsearch</artifactId>
  13. <version>0.0.1-SNAPSHOT</version>
  14. <name>Elasticsearch</name>
  15. <description>Demo project for Spring Boot</description>
  16. <properties>
  17. <java.version>1.8</java.version>
  18. </properties>
  19. <dependencies>
  20. <dependency>
  21. <groupId>org.springframework.boot</groupId>
  22. <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
  23. </dependency>
  24. <dependency>
  25. <groupId>org.springframework.boot</groupId>
  26. <artifactId>spring-boot-starter-test</artifactId>
  27. <scope>test</scope>
  28. </dependency>
  29. <dependency>
  30. <groupId>org.projectlombok</groupId>
  31. <artifactId>lombok</artifactId>
  32. </dependency>
  33. </dependencies>
  34. <build>
  35. <plugins>
  36. <plugin>
  37. <groupId>org.springframework.boot</groupId>
  38. <artifactId>spring-boot-maven-plugin</artifactId>
  39. <version>2.3.2.RELEASE</version>
  40. </plugin>
  41. </plugins>
  42. </build>
  43. </project>

配置yml连接Elasticsearch

  1. spring:
  2. elasticsearch:
  3. rest:
  4. uris:
  5. - http://192.168.64.181:9200
  6. - http://192.168.64.181:9201
  7. - http://192.168.64.181:9202
  8. logging:
  9. level:
  10. tracer: trace

创建Student类

  1. @Document(indexName = "students", shards = 3, replicas = 2)
  2. @Data
  3. @NoArgsConstructor
  4. @AllArgsConstructor
  5. @Accessors(chain = true)
  6. public class Student {
  7. /**
  8. * 使用学号作为索引id
  9. */
  10. @Id
  11. private Long id;
  12. private String name;
  13. private Character gender;
  14. /**
  15. * es索引中的字段名,使用Field注解指定,与变量名同名可以省略
  16. */
  17. @Field("birthDate")
  18. private String birthDate;
  19. }

注解及参数说明

  • @Document():标识要持久化到 Elasticsearch 的域对象
    • shards:索引indexName()的分片数。 用于创建索引。默认为1.
    • replicas:索引indexName()的副本数。 用于创建索引。默认为1.
    • `refreshInterval:索引indexName()刷新间隔,默认为1s.
    • indexStoreType:索引indexName()索引存储类型,
    • indexName索引名称,命名要求如下:
      • 仅小写
      • , |, (空格字符), ,, #/li>
      • 不能以 -、_、+ 开头
      • 不可能是 。 或者 ..
      • 不能超过 255 个字节(注意它是字节,因此多字节字符将更快地计入 255 个限制)
  • @Id:标识该属性为id,在 Elasticsearch 中创建文档时,使用 @Id 注解的字段作为文档的 _id
  • @Field:设置字段的数据类型和其他属性。

创建StudentRepository接口继承ElasticsearchRepository接口

Spring Data 的 Repository 接口提供了一种声明式的数据操作规范,无序编写任何代码,只需遵循 Spring Data 的方法定义规范即可完成数据的 CRUD 操作。spring data es repository API只需要定义接口继承ElasticsearchRepository,基础增删改查方法,在父接口中已定义。可以通过继承ElasticsearchRepository接口添加自定义的数据操作方法。

Repository 方法命名规范

https://www.yuque.com/yiquanchaoren-dvwhg/javassm/arwhgdvgif4s?inner=HoIhB

  1. public interface StudentRepository extends ElasticsearchRepository<Student, Long> {
  2. /**
  3. * 在name字段搜索关键词
  4. *
  5. * @param key 搜索使用的关键词
  6. * @return {@link List}<{@link Student}> 学生信息列表
  7. */
  8. List<Student> findByName(String key);
  9. /**
  10. * 在name字段中搜索关键词,或者使用birthDate字段匹配指定日期
  11. *
  12. * @param name 名字
  13. * @param birthDate 出生日期
  14. * @return {@link List}<{@link Student}> 符合要求的学生信息
  15. */
  16. List<Student> findByNameOrBirthDate(String name, String birthDate);
  17. }

进行测试

  1. @SpringBootTest
  2. public class Test01 {
  3. private final StudentRepository studentRepository;
  4. @Autowired
  5. public Test01(StudentRepository studentRepository) {
  6. this.studentRepository = studentRepository;
  7. }
  8. @Test
  9. public void test1() {
  10. //在es服务器的students索引中保存学生信息
  11. studentRepository.save(new Student(1001L, "马大钊", '女', "0659-11-04"));
  12. studentRepository.save(new Student(1002L, "马二钊", '女', "0659-11-05"));
  13. studentRepository.save(new Student(1003L, "马三钊", '女', "0659-11-06"));
  14. studentRepository.save(new Student(1004L, "马四钊", '女', "0659-11-07"));
  15. studentRepository.save(new Student(1005L, "马五钊", '女', "0659-11-08"));
  16. studentRepository.save(new Student(1006L, "马六钊", '女', "0659-11-09"));
  17. studentRepository.save(new Student(1007L, "马七钊", '女', "0659-11-10"));
  18. studentRepository.save(new Student(1008L, "马小钊", '女', "0659-11-11"));
  19. }
  20. @Test
  21. public void test2() {
  22. studentRepository.save(new Student(1001L, "马王堆", '?', "0023-11-04"));
  23. }
  24. @Test
  25. public void test3() {
  26. Optional<Student> stu = studentRepository.findById(1001L);
  27. //判断Optional对象中是否存在Student对象
  28. if (stu.isPresent()) {
  29. System.out.println("-------------------------------" + stu + "---------------------------------");
  30. }
  31. Iterable<Student> students = studentRepository.findAll();
  32. for (Student student : students) {
  33. System.out.println(student);
  34. }
  35. }
  36. @Test
  37. public void test4() {
  38. studentRepository.deleteById(1008L);
  39. }
  40. @Test
  41. public void test5() {
  42. List<Student> studentList = studentRepository.findByName("马王");
  43. for (Student student : studentList) {
  44. System.out.println(student);
  45. }
  46. }
  47. @Test
  48. public void test6() {
  49. List<Student> students = studentRepository.findByNameOrBirthDate("堆", "0659-11-05");
  50. for (Student student : students) {
  51. System.out.println(student);
  52. }
  53. }
  54. }

使用 Criteria 构建自定义查询

Criteria数据查询

  • 使用Criteria封装搜索条件
  • CriteriaQuery封装Criteria条件对象和分页参数
  • 注入ElasticsearchOperations对象进行查询

创建Criteria查询类

  1. @Component
  2. public class StudentSearch {
  3. private final ElasticsearchOperations operations;
  4. @Autowired
  5. public StudentSearch(ElasticsearchOperations operations) {
  6. this.operations = operations;
  7. }
  8. /**
  9. * 按名称搜索
  10. *
  11. * @param key 关键
  12. * @return {@link List}<{@link Student}> 符合条件的学生列表
  13. */
  14. public List<Student> searchByName(String key) {
  15. Criteria criteria = new Criteria("name");
  16. //设置条件
  17. criteria.is(key);
  18. return exec(criteria);
  19. }
  20. private List<Student> exec(Criteria criteria) {
  21. //将搜索条件封装之Query对象
  22. CriteriaQuery query = new CriteriaQuery(criteria);
  23. List<Student> list = new ArrayList<>();
  24. /*
  25. 使用ElasticsearchOperations工具类执行查询,需要进行依赖注入
  26. SearchHit对象中包含学生数据,相关度得分
  27. */
  28. SearchHits<Student> search = operations.search(query, Student.class);
  29. for (SearchHit<Student> searchHit : search) {
  30. Student stu = searchHit.getContent();
  31. list.add(stu);
  32. }
  33. return list;
  34. }
  35. /**
  36. * 根据出生日期进行搜索
  37. *
  38. * @param from 开始日期
  39. * @param to 结束日期
  40. * @return {@link List}<{@link Student}> 符合条件的学生列表
  41. */
  42. public List<Student> searchByBirthDate(String from, String to) {
  43. Criteria criteria = new Criteria("birthDate");
  44. criteria.between(from, to);
  45. return exec(criteria);
  46. }
  47. }

进行测试

  1. @SpringBootTest
  2. public class Test02 {
  3. private final StudentSearch search;
  4. @Autowired
  5. public Test02(StudentSearch search) {
  6. this.search = search;
  7. }
  8. @Test
  9. public void test1(){
  10. List<Student> list = search.searchByName("马");
  11. for (Student student : list) {
  12. System.out.println(student);
  13. }
  14. }
  15. @Test
  16. public void test2(){
  17. List<Student> list = search.searchByBirthDate("0001-01-01", "2021-11-04");
  18. for (Student student : list) {
  19. System.out.println(student);
  20. }
  21. }
  22. }

Criteria分页查询和高亮

分页

  • Pageable—-向服务器提交的分页参数,page(页数),size(每页的记录数)
  • Page ————从服务器返回的一页数据,数据列表,分页信息(可选,可直接使用List<?>)
  • Repository

    1. Page<Student> findByName(String key, Pageable pageable);
  • Criteria

    1. Criteria criteria = new Criteria(args);
    2. CriteriaQuery query = new CriteriaQuery(criteria);
    3. query.setPageable(pageable);

创建接口

  1. public interface StudentRepository extends ElasticsearchRepository<Student, Long> {
  2. /**
  3. * 在name字段中搜索关键词,或者使用birthDate字段匹配指定日期进行分页查询
  4. *
  5. * @param name 名字
  6. * @param birthDate 出生日期
  7. * @param pageable 分页参数
  8. * @return {@link List}<{@link Student}>
  9. */
  10. Page<Student> findByNameOrBirthDate(String name, String birthDate, Pageable pageable);
  11. }

进行测试

  1. @SpringBootTest
  2. public class Test01 {
  3. private final StudentRepository studentRepository;
  4. @Autowired
  5. public Test01(StudentRepository studentRepository) {
  6. this.studentRepository = studentRepository;
  7. }
  8. @Test
  9. public void test7() {
  10. Pageable pageable = PageRequest.of(1, 2);
  11. Page<Student> students = studentRepository.findByNameOrBirthDate("马", "0659-11-05", pageable);
  12. System.out.println("共有几页:" + students.getTotalPages());
  13. System.out.println("是否有上一页:" + students.hasPrevious());
  14. System.out.println("是否有下一页:" + students.hasNext());
  15. System.out.println("每页大小:" + students.getNumber());
  16. for (Student student : students) {
  17. System.out.println(student);
  18. }
  19. }
  20. }