ElasticSearch7入门(六)SpringBoot2.3.0集成ElasticSearch7.5.2-SpringData

228 阅读2分钟

背景

上一篇使用HighLevelClient的方式实现了SpringBoot集成ElasticSearch。今天换作SpringDataElasticsearch来完成SpringBootElasticSearch的集成。SpringData系列借助自定义的命名规则,直接定义完接口,它可以帮助我们自动实现接口。

核心依赖

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

领域模型

package com.heartsuit.domain;

import com.fasterxml.jackson.annotation.JsonFormat;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.DateFormat;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;

import java.time.LocalDateTime;

/**
 * @Author Heartsuit
 * @Date 2020-06-12
 */
@Data
//@Document(indexName = "book", useServerConfiguration = true, createIndex = false)
@Document(indexName = "book")
public class Book {
    @Id
    private String id;

    @Field(type = FieldType.Text)
    private String title;

    @Field(type = FieldType.Keyword, analyzer = "ik_smart", searchAnalyzer = "ik_smart")
    private String author;

    @Field(name = "word_count", type = FieldType.Integer)
    private Integer wordCount;

    /**
     * 1. Jackson日期时间序列化问题:
     * Cannot deserialize value of type `java.time.LocalDateTime` from String "2020-06-04 15:07:54": Failed to deserialize java.time.LocalDateTime: (java.time.format.DateTimeParseException) Text '2020-06-04 15:07:54' could not be parsed at index 10
     * 解决:@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     * 2. 日期在ES存为long类型
     * 解决:需要加format = DateFormat.custom
     * 3. java.time.DateTimeException: Unable to obtain LocalDate from TemporalAccessor: {DayOfMonth=5, YearOfEra=2020, MonthOfYear=6},ISO of type java.time.format.Parsed
     * 解决:pattern = "uuuu-MM-dd HH:mm:ss" 即将yyyy改为uuuu,或8uuuu: pattern = "8uuuu-MM-dd HH:mm:ss"
     * 参考:https://www.elastic.co/guide/en/elasticsearch/reference/current/migrate-to-java-time.html#java-time-migration-incompatible-date-formats
     */
    @JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss")
    @Field(name = "publish_date", type = FieldType.Date, format = DateFormat.custom, pattern = "uuuu-MM-dd HH:mm:ss")
    private LocalDateTime publishDate;
}

核心方法

package com.heartsuit.repository;

import java.util.List;
import com.heartsuit.domain.Book;
import org.springframework.data.elasticsearch.annotations.Query;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;

/**
 * @Author Heartsuit
 * @Date 2020-06-12
 */
public interface BookRepository extends ElasticsearchRepository<Book, String> {
  List<Book> findByAuthor(String author);
  List<Book> findByAuthorLike(String author);
  List<Book> findByTitle(String author);
  List<Book> findByWordCount(Integer wordCount);
  List<Book> findByAuthorAndTitle(String author, String title);

  @Query("{\"bool\" : {\"must\" : {\"match\" : {\"title\" : \"?0\"}}}}")
  List<Book> queryByTitle(String keyword);
}

测试接口

package com.heartsuit.controller;

import com.heartsuit.domain.Book;
import com.heartsuit.repository.BookRepository;
import lombok.extern.slf4j.Slf4j;
import org.springframework.format.annotation.DateTimeFormat;
import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime;
import java.util.*;

/**
 * @Author Heartsuit
 * @Date 2020-06-12
 */
@RestController
@RequestMapping("/books")
@Slf4j
public class BookController {
    private final BookRepository bookRepository;

    public BookController(BookRepository bookRepository) {
        this.bookRepository = bookRepository;
    }

    @GetMapping("/all")
    public List<Book> findAll() {
        Iterable<Book> result = bookRepository.findAll();
        Iterator<Book> res = result.iterator();
        List<Book> books = new ArrayList<>();
        while (res.hasNext()) {
            books.add(res.next());
        }
        log.info("List All, Size: {}", books.size());
        return books;
    }

    /**
     * 新增
     *
     * @param book
     * @return
     */
    @PostMapping("/")
    public Book create(@RequestBody Book book) {
        log.info("Saved OK: {}", book.getTitle());
        return bookRepository.save(book);
    }

    /**
     * 根据ID查询
     *
     * @param id
     * @return
     */
    @GetMapping("/{id}")
    public Book findById(@PathVariable("id") String id) {
        log.info("Query ID: {}", id);
        Book orElse = bookRepository.findById(id).orElse(null);
        return orElse;
    }

    /**
     * 根据ID修改
     *
     * @param id
     * @param title
     * @param author
     * @param wordCount
     * @param publishDate
     * @return
     * Note: 报错:Failed to convert value of type 'java.lang.String' to required type 'java.time.LocalDateTime';
     * 解决:在参数前添加注解:@DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss")
     */
    @PutMapping("/{id}")
    public Book update(@PathVariable("id") String id,
                       @RequestParam(name = "title", required = false) String title,
                       @RequestParam(name = "author", required = false) String author,
                       @RequestParam(name = "wordCount", required = false) Integer wordCount,
                       @RequestParam(name = "publishDate", required = false) @DateTimeFormat(pattern = "yyyy-MM-dd HH:mm:ss") LocalDateTime publishDate) {
        Optional<Book> optional = bookRepository.findById(id);
        if (optional.isPresent()) {
            Book book = optional.get();
            if (title != null) {
                book.setTitle(title);
            }
            if (author != null) {
                book.setAuthor(author);
            }
            if (wordCount != null) {
                book.setWordCount(wordCount);
            }
            if (publishDate != null) {
                book.setPublishDate(publishDate);
            }
            return bookRepository.save(book);
        }
        return null;
    }

    /**
     * 根据ID删除
     *
     * @param id
     */
    @DeleteMapping("/{id}")
    public void delete(@PathVariable("id") String id) {
        log.info("Deleted ID: {}", id);
        bookRepository.deleteById(id);
    }

    /**
     * 删除所有
     */
    @PostMapping("/clear")
    public void clear() {
        log.info("Delete All!");
        bookRepository.deleteAll();
    }

    /**
     * 根据作者查询
     *
     * @param author
     * @return
     */
    @PostMapping("/author")
    public List<Book> byAuthor(String author) {
        log.info("By Author");
        return bookRepository.findByAuthor(author);
    }

    /**
     * 根据作者检索
     *
     * @param author
     * @return
     */
    @PostMapping("/author/like")
    public List<Book> byAuthorLike(String author) {
        log.info("By Author Like");
        return bookRepository.findByAuthorLike(author);
    }

    /**
     * 根据标题查询
     *
     * @param title
     * @return
     */
    @PostMapping("/title")
    public List<Book> byTitle(String title) {
        log.info("By Title");
        return bookRepository.findByTitle(title);
    }

    /**
     * 根据字数查询
     *
     * @param wordCount
     * @return
     */
    @GetMapping("/wordCount/{count}")
    public List<Book> byWordCount(@PathVariable("count") Integer wordCount) {
        log.info("By WordCount");
        return bookRepository.findByWordCount(wordCount);
    }

    /**
     * 根据作者与标题查询
     *
     * @param author
     * @param title
     * @return
     */
    @PostMapping("/query")
    public List<Book> byAuthorAndTitle(String author, String title) {
        log.info("By AuthorAndTitle");
        return bookRepository.findByAuthorAndTitle(author, title);
    }

    /**
     * 根据标题查询@Query
     *
     * @param title
     * @return
     */
    @PostMapping("/query/title")
    public List<Book> queryByTitle(String title) {
        log.info("Query By Title");
        return bookRepository.queryByTitle(title);
    }
}

Source Code

Github

Done~😎


If you have any questions or any bugs are found, please feel free to contact me.

Your comments and suggestions are welcome!

本文已参与「新人创作礼」活动,一起开启掘金创作之路。