Springboot integrates Elasticsearch

1. Introduce dependencies

<dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>

2. Two methods to configure ElasticSearch settings

1. Configure in application.yml

spring:
  data:
    elasticsearch:
      cluster-nodes: localhost:9300
      cluster-name: es-wyf

2. Configure using configuration classes

/**
 * ElasticSearch client configuration

 */
@Configuration
public class RestClientConfig extends AbstractElasticsearchConfiguration {
    @Override
    @Bean
    public RestHighLevelClient elasticsearchClient() {
        final ClientConfiguration clientConfiguration = ClientConfiguration.builder()
                .connectedTo("localhost:9200")
                .build();
        return RestClients.create(clientConfiguration).rest();
    }
}

3. Write an entity class and use this entity class to operate ES’s CRUD

@Data
@Accessors(chain = true)
@Document(indexName = "blog", type = "java")
public class BlogModel implements Serializable {

    private static final long serialVersionUID = 6320548148250372657L;

    @Id
    private String id;

    private String title;

    //@Field(type = FieldType.Date, format = DateFormat.basic_date)
    @DateTimeFormat(pattern = "yyyy-MM-dd")
    @JsonFormat(pattern = "yyyy-MM-dd", timezone = "GMT + 8")
    private Date time;
}
public interface BlogRepository extends ElasticsearchRepository<BlogModel, String> {
}

4. Write the Controller class to inject the business class and use ES CURD

@RestController
@RequestMapping("/blog")
public class BlogController {
    @Autowired
    private BlogRepository blogRepository;
//You can also change it to the business class that comes with ES
    //@Autowired
    //private ElasticsearchTemplate elasticsearchTemplate;

    //Add ES data
   @PostMapping("/add")
    public Result add(@RequestBody BlogModel blogModel) {
     blogRepository.save(blogModel);
     return Result.success();

    //Query the data in a single ES
   @GetMapping("/get/{id}")
   public Result getById(@PathVariable String id) {
    if (StringUtils.isEmpty(id))
        return Result.error();
    Optional<BlogModel> blogModelOptional = blogRepository.findById(id);
    if (blogModelOptional.isPresent()) {
        BlogModel blogModel = blogModelOptional.get();
        return Result.success(blogModel);
    }
    return Result.error();
  }

//Get all data
  @GetMapping("/get")
public Result getAll() {
    Iterable<BlogModel> iterable = blogRepository.findAll();
    List<BlogModel> list = new ArrayList<>();
    iterable.forEach(list::add);
    return Result.success(list);
}

//update data
@PostMapping("/update")
public Result updateById(@RequestBody BlogModel blogModel) {
    String id = blogModel.getId();
    if (StringUtils.isEmpty(id))
        return Result.error();
    blogRepository.save(blogModel);
    return Result.success();
}

//Delete a single piece of data
@DeleteMapping("/delete/{id}")
public Result deleteById(@PathVariable String id) {
    if (StringUtils.isEmpty(id))
        return Result.error();
    blogRepository.deleteById(id);
    return Result.success();
}

//Delete all data
@DeleteMapping("/delete")
public Result deleteById() {
    blogRepository.deleteAll();
    return Result.success();
}


}
}

5. Some well-written ES search examples

1. Global search

/**
 * research all
 * @param keyword keyword
 * @param page current page, starting from 0
 * @param size size per page
 * @return {@link Result} The received data format is json
 */
@GetMapping("/full")
public Mono<Result> full(String keyword, int page, int size) {
    // System.out.println(new Date() + " => " + keyword);

    //Verify parameters
    if (StringUtils.isEmpty(page))
        page = 0; // if page is null, page = 0
    
    if (StringUtils.isEmpty(size))
        size = 10; // if size is null, size default 10
    
    // Construct paging class
    Pageable pageable = PageRequest.of(page, size);
    
    //Construct query NativeSearchQueryBuilder
    NativeSearchQueryBuilder searchQueryBuilder = new NativeSearchQueryBuilder()
            .withPageable(pageable)
            ;
    if (!StringUtils.isEmpty(keyword)) {
        // keyword must not null
        searchQueryBuilder.withQuery(QueryBuilders.queryStringQuery(keyword));
    }
    
    /*
    SearchQuery
    This is very critical. This is the entrance to the search conditions.
    elasticsearchTemplate will use it to search
     */
    SearchQuery searchQuery = searchQueryBuilder.build();

    // page search
    Page<PhoneModel> phoneModelPage = elasticsearchTemplate.queryForPage(searchQuery, PhoneModel.class);
    
    // return
    return Mono.just(Result.success(phoneModelPage));
}

2.

/**
 * Advanced search, search based on fields
 * @param name name
 * @param color color
 * @param sellingPoint selling point
 * @param price price
 * @param start start time (format: yyyy-MM-dd HH:mm:ss)
 * @param end end time (format: yyyy-MM-dd HH:mm:ss)
 * @param page current page, starting from 0
 * @param size size of each page
 * @return {@link Result}
 */
@GetMapping("/_search")
public Mono<Result> search(String name, String color, String sellingPoint, String price, String start, String end, int page, int size) {

    //Verify parameters
    if (StringUtils.isEmpty(page) || page < 0)
        page = 0; // if page is null, page = 0

    if (StringUtils.isEmpty(size) || size < 0)
        size = 10; // if size is null, size default 10
    
    //Construct paging object
    Pageable pageable = PageRequest.of(page, size);

    // BoolQueryBuilder (Elasticsearch Query)
    BoolQueryBuilder boolQueryBuilder = new BoolQueryBuilder();
    if (!StringUtils.isEmpty(name)) {
        boolQueryBuilder.must(QueryBuilders.matchQuery("name", name));
    }

    if (!StringUtils.isEmpty(color)) {
        boolQueryBuilder.must(QueryBuilders.matchQuery("colors", color));
    }

    if (!StringUtils.isEmpty(color)) {
        boolQueryBuilder.must(QueryBuilders.matchQuery("sellingPoints", sellingPoint));
    }

    if (!StringUtils.isEmpty(price)) {
        boolQueryBuilder.must(QueryBuilders.matchQuery("price", price));
    }

    if (!StringUtils.isEmpty(start)) {
        Date startTime = null;
        try {
            startTime = DateTimeUtil.stringToDate(start, DateTimeFormat.yyyy_MM_dd_HH_mm_ss);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").gt(startTime.getTime()));
    }

    if (!StringUtils.isEmpty(end)) {
        Date endTime = null;
        try {
            endTime = DateTimeUtil.stringToDate(end, DateTimeFormat.yyyy_MM_dd_HH_mm_ss);
        } catch (ParseException e) {
            e.printStackTrace();
        }
        boolQueryBuilder.must(QueryBuilders.rangeQuery("createTime").lt(endTime.getTime()));
    }

    // BoolQueryBuilder (Spring Query)
    SearchQuery searchQuery = new NativeSearchQueryBuilder()
            .withPageable(pageable)
            .withQuery(boolQueryBuilder)
            .build()
            ;

    // page search
    Page<PhoneModel> phoneModelPage = elasticsearchTemplate.queryForPage(searchQuery, PhoneModel.class);
    
    // return
    return Mono.just(Result.success(phoneModelPage));
}