Spring Data ElasticSearch
2023年2月3日
Spring Data ElasticSearch 版本对应关系
https://docs.spring.io/spring-data/elasticsearch/docs/current/reference/html/#preface.versions
这里我们选择:
- Spring Boot版本为
2.4.2
- Elasticsearch版本为
7.9.3
- Spring Data Elasticsearc版本为
4.1.3
文档参考地址:https://docs.spring.io/spring-data/elasticsearch/docs/4.1.3/reference/html/#reference - 中文分词器版本为
7.9.3
- Kibana版本为
7.9.3
新建SpringBoot项目
导入所需依赖
- spring-boot-starter-data-elasticsearch 2.4.2
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.4.2</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<groupId>org.lc</groupId>
<artifactId>spring-data-es</artifactId>
<version>0.0.1-SNAPSHOT</version>
<name>spring-data-es</name>
<description>Demo project for Spring Boot</description>
<properties>
<java.version>1.8</java.version>
</properties>
<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-web</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.1</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
<encoding>UTF-8</encoding>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>
</project>
实体
@Data
//indexName 创建文档名 book
//shards 分片数 2
//replicas 副本数 2
//createIndex 若没有索引会自动创建
@Document(indexName = "books", shards = 3, replicas = 2, createIndex = true)
public class Book {
//文档唯一id
@Id
private String id;
//type 指定字段类型
@Field(type = FieldType.Keyword)
private String[] author;
@Field(type = FieldType.Double)
private String price;
@Field(type = FieldType.Keyword)
private String publish;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String name;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String type;
@Field(type = FieldType.Text,analyzer = "ik_max_word")
private String info;
}
Repository
public interface BookRepository extends ElasticsearchRepository<Book, String> {
/**
* 查询 name 或者 info 字段中包含指定关键字的文档
* term不会对要查询的关键字进行分词
* ?0 代表第一个参数
* ?1 代表第二个参数 以此类推
*/
@Query("{\n" +
" \"bool\": {\n" +
" \"should\": [\n" +
" {\n" +
" \"term\": {\n" +
" \"name\": {\n" +
" \"value\": \"?0\"\n" +
" }\n" +
" }\n" +
" },\n" +
" {\n" +
" \"term\": {\n" +
" \"info\": {\n" +
" \"value\": \"?1\"\n" +
" }\n" +
" }\n" +
" }\n" +
" ]\n" +
" }\n" +
"}")
Page<Book> findByNameOrInfoAnnotation(String name, String info, Pageable pageable);
/*
* 查询 name 或者 info 字段为指定关键字的文档
* 以下两种方式均可:通过 queryBy 或者 findBy 方式查询均可,都是通过 复合查询 中的 bool 查询进行实现
* 参考文档:https://docs.spring.io/spring-data/elasticsearch/docs/4.1.3/reference/html/#elasticsearch.repositories
*/
Page<Book> queryByNameOrInfo(String keyword1, String keyword2, Pageable pageable);
// Page<Book> findByNameOrInfo(String keyword1, String keyword2, Pageable pageable);
/**
* 查询 name 并且 info 字段为指定关键字的文档
*/
Page<Book> queryByNameAndInfo(String keyword1, String keyword2, Pageable pageable);
/**
* 查询 name 或者 info 中指定的关键字的文档 并且在 name 和 info 中匹配的关键字加高亮
*/
@Highlight(fields = {
@HighlightField(name = "name"),
@HighlightField(name = "info")
})
SearchPage<Book> findByNameOrInfo(String name, String info, Pageable pageable);
/**
* 查询 name 字段中包含指定关键字的文档
* 并且查询的关键字会在 info 和 name 字段中高亮显示
*/
@Highlight(fields = {
@HighlightField(name = "name"),
@HighlightField(name = "info")
}, parameters = @HighlightParameters(requireFieldMatch = false))
SearchPage<Book> findByName(String name, Pageable pageable);
}
service
@Service
public class BookService {
@Autowired
private BookRepository bookRepository;
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
/**
* 添加多个文档
*/
public int importBook(List<Book> list) {
Iterable<Book> books = bookRepository.saveAll(list);
int count=0;
Iterator<Book> iterator = books.iterator();
while (iterator.hasNext()) {
count++;
iterator.next();
}
return count;
}
/**
* 根据id删除文档 若没有传文档id则删除所有文档
*/
public boolean deleteBookById(String id) {
try {
if (!StringUtils.isEmpty(id)) {
bookRepository.deleteById(id);
}else{
bookRepository.deleteAll();;
}
return true;
} catch (Exception e) {
e.printStackTrace();
return false;
}
}
/**
* 注解形式:查询 name 或者 info 字段中包含指定关键字的文档
*/
public Object searchNameOrInfoAnnotation(String name, String info, int page, int size) {
return bookRepository.findByNameOrInfoAnnotation(name, info, PageRequest.of(page - 1, size));
}
/**
* 查询 name 或者 info 字段中包含指定关键字的文档
*/
public Object queryByNameOrInfo(String keyword, int page, int size) {
return bookRepository.queryByNameAndInfo(keyword, keyword, PageRequest.of(page - 1, size));
}
/**
* 查询 name 或者 info 字段中包含关键字的文档 并且 name 和 info 中的关键字高亮
*/
public Object searchHighlightNameOrInfo(String name, String info, int page, int size) {
return bookRepository.findByNameOrInfo(name, info,PageRequest.of(page - 1, size));
}
/**
* 查询 name 中指定的关键字 并且 name 和 info 的关键字高亮
*/
public Object searchHighlightName(String name, int page, int size) {
SearchPage<Book> searchHits = bookRepository.findByName(name, PageRequest.of(page - 1, size));
List<SearchHit<Book>> searchHitList = searchHits.getContent();
ArrayList<Book> bookArrayList = new ArrayList<>(searchHitList.size());
for (SearchHit<Book> bookSearchHit : searchHitList) {
Book book = bookSearchHit.getContent();
Map<String, List<String>> highlightFields = bookSearchHit.getHighlightFields();
if (highlightFields.size() > 0) {
BeanMap beanMap = BeanMap.create(book);
highlightFields.forEach((k,v)->{
StringBuilder sb=new StringBuilder();
if (v.size() > 0) {
v.forEach(sb::append);
}
beanMap.put(k,sb.toString());
});
}
bookArrayList.add(book);
}
return bookArrayList;
}
}
controller
@RestController
@RequestMapping("/book")
public class BookController {
@Autowired
private BookService bookService;
/**
* 新增
*
* @param list
* @return
*/
@PostMapping("/add")
public int importBook(@RequestBody List<Book> list) {
return bookService.importBook(list);
}
/**
* 删除
* 删除指定id文档 或者 删除索引文档
*
* @param id
* @return
*/
@DeleteMapping({"/delete/{id}", "/delete"})
public boolean deleteBookById(@PathVariable(value = "id", required = false) String id) {
return bookService.deleteBookById(id);
}
@GetMapping("/query_name_info/anno")
public Object searchNameOrInfoAnnotation(
@RequestParam("name") String name,
@RequestParam("info") String info,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "size", required = false, defaultValue = "10") int size) {
return bookService.searchNameOrInfoAnnotation(name, info, page, size);
}
@GetMapping("/query_name_info")
public Object queryByNameOrInfo(
@RequestParam(value = "keyword", required = false) String keyword,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "size", required = false, defaultValue = "10") int size
) {
return bookService.queryByNameOrInfo(keyword, page, size);
}
@GetMapping("/highlight_name_or_info")
public Object searchHighlightNameOrInfo(
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "info", required = false) String info,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "size", required = false, defaultValue = "10") int size
) {
return bookService.searchHighlightNameOrInfo(name, info, page, size);
}
@GetMapping("/highlight_name")
public Object searchHighlightNameOrInfo(
@RequestParam(value = "name", required = false) String name,
@RequestParam(value = "page", required = false, defaultValue = "1") int page,
@RequestParam(value = "size", required = false, defaultValue = "10") int size
) {
return bookService.searchHighlightName(name, page, size);
}
}
properties配置
# 应用名称
spring.application.name=spring-data-es
# 应用服务 WEB 访问端口
server.port=8080
spring.elasticsearch.rest.uris=http://localhost:9200