目录
1. 安装ElasticSearch等相关软件
Windows Docker 安装 ElasticSearch_全栈编程网的博客-CSDN博客
2. 概述
这种方式是spring-data提取了共性的CRUD功能,根据不同的操作资源实现不同的操作,如果操作的是MySQL那么就有 spring-data-mysql 实现对MySQL的CRUD功能。
Spring-data-elasticsearch方式,通过创建一个Repository接口 继承 ElasticsearchRepository 接口方式获取操作ElasticSearch的CRUD功能。
3. 项目代码
3.1 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.10</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
<version> 1.2.70</version>
</dependency>
3.2 application.yml配置
spring:
application:
name: demo
elasticsearch:
uris: http://localhost:9200
server:
port: 8081
3.3 创建索引hello对应的实体类
ElasticSearch 中有个索引 hello,这个实体类定义了索引的映射关系,每个属性都是索引对应mapping字段的设置,例如可以设置字段的类型,是否分词等信息,后面调用接口创建索引会根据这个类创建对应ES里面的索引hello
@Data
@NoArgsConstructor
@Accessors(chain = true)
@Document(indexName = "hello")
public class HelloEntity {
@Id
private Long id;
@Field(type = FieldType.Keyword)
private String firstCode;
@Field(type = FieldType.Keyword)
private String secordCode;
@Field(type = FieldType.Text, analyzer = "ik_max_word")
private String content;
@Field(type = FieldType.Integer)
private Integer type;
public HelloEntity(Long id, String firstCode, String secordCode, String content, Integer type){
this.id=id;
this.firstCode=firstCode;
this.secordCode=secordCode;
this.content=content;
this.type=type;
}
}
3.4 创建CRUD的dao
spring-data-elasticsearch 中 ElasticSearchRepository 实现了对ElasticSearch 的CRUD操作,只要定义个HelloDao接口集成这个接口,就继承了CRUD功能。
对于自定义的对ES的操作方法,类似于jpa语法定义方法,就可以实现对ES的操作,如代码中例子所示,具体语法可以去学习一下
import java.util.List;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.annotations.Highlight;
import org.springframework.data.elasticsearch.annotations.HighlightField;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import com.example.es.entity.HelloEntity;
public interface HelloDao extends ElasticsearchRepository<HelloEntity, Long> {
/**
* 自定义ID范围查询
* @param begin
* @param end
* @param pageable
* @return
*/
Page<HelloEntity> findByIdBetween(int begin, int end, PageRequest pageable);
/**
* 自定义查询 ,高亮显示 firstCode
* @param firstCode
* @param secordCode
* @return
*/
@Highlight(fields = {
@HighlightField(name = "firstCode"),
@HighlightField(name = "secordCode")
})
List<SearchHit<HelloEntity>> findByFirstCodeOrSecordCode(String firstCode, String secordCode);
/**
* 模糊查询content
* @param content
* @return
*/
@Highlight(fields = {
@HighlightField(name = "content")
})
List<SearchHit<HelloEntity>> findByContent(String content);
}
3.5 创建测试用的Controller类
集成了新建索引、删除索引、CRUD数据、分页查询、模糊查询、高亮显示等接口,基本涵盖了平时对ES的操作功能。
@RestController
@RequestMapping("es")
public class ElasticSearchController {
@Autowired
private ElasticsearchRestTemplate elasticsearchRestTemplate;
@Autowired
private HelloDao helloDao;
/**
* 创建索引 hello
* @return
*/
@GetMapping("/createIndex")
public String create() {
boolean b = elasticsearchRestTemplate.indexOps(HelloEntity.class).create();
if (b) {
return "success";
}
return "fail";
}
/**
* 创建索引 hello,并创建mapping
* @return
*/
@GetMapping("/createIndexWithMapping")
public String createMapping() {
boolean b = elasticsearchRestTemplate.indexOps(HelloEntity.class).createWithMapping();
if (b) {
return "success";
}
return "fail";
}
/**
* 删除索引 hello
* @return
*/
@GetMapping("/deleteIndex")
public String deleteIndex() {
boolean b = elasticsearchRestTemplate.indexOps(HelloEntity.class).delete();
if (b) {
return "success";
}
return "fail";
}
/**
* 往hello索引中插入数据
* @param entity
* @return
*/
@PostMapping
public String add(@RequestBody HelloEntity entity) {
HelloEntity save = helloDao.save(entity);
System.out.println(save);
return "success";
}
/**
* 修改hello索引中的数据,根据ID修改
* @param entity
* @return
*/
@PutMapping
public String update(@RequestBody HelloEntity entity) {
HelloEntity save = helloDao.save(entity);
return "success";
}
/**
* 根据ID查询数据
* @param id
* @return
*/
@GetMapping("/{id}")
public String get(@PathVariable(value = "id") Long id) {
Optional<HelloEntity> byId = helloDao.findById(id);
boolean present = byId.isPresent();
if (present) {
return JSON.toJSONString(byId.get());
}
return null;
}
/**
* 分页查询
* @param pageDTO
* @return
*/
@GetMapping
public String getAll(@RequestBody PageDTO pageDTO) {
PageRequest pageable = PageRequest.of(pageDTO.getPage(), pageDTO.getSize());
Page<HelloEntity> all = helloDao.findAll(pageable);
return JSON.toJSONString(all);
}
/**
* 删除
* @param id
* @return
*/
@DeleteMapping("/{id}")
public String delete(@PathVariable(value = "id") Long id) {
helloDao.deleteById(id);
return "success";
}
/**
* 根据ID范围查询
* @return
*/
@GetMapping("/idBetween")
public String idBetween(@RequestParam(value = "begin") int begin,
@RequestParam(value = "end") int end,
@RequestParam(value = "page") int page,
@RequestParam(value = "size") int size
) {
PageRequest pageable = PageRequest.of(page, size);
Page<HelloEntity> all = helloDao.findByIdBetween(begin, end, pageable);
return JSON.toJSONString(all);
}
/**
* 根据 firstCode
* secordCode 查询
* @return
*/
@GetMapping("/findByFirstCodeOrSecordCode")
public String query(@RequestParam(value = "firstCode", required = false) String firstCode,
@RequestParam(value = "secordCode", required = false) String secordCode
) {
List<SearchHit<HelloEntity>> all = helloDao.findByFirstCodeOrSecordCode(firstCode, secordCode);
return JSON.toJSONString(all);
}
/**
* 模糊查询ik分词器分词的content字段
* @return
*/
@GetMapping("/findByContent")
public String queryContent(@RequestParam(value = "content", required = false) String content
) {
List<SearchHit<HelloEntity>> all = helloDao.findByContent(content);
return JSON.toJSONString(all);
}
}
DTO参数类
@Data
public class PageDTO {
private Integer page = 0;
private Integer size = 10;
}
4. 启动SpringBoot,测试CRUD
调用相关接口测试功能。
4.1 创建ES索引hello和mapping
调用接口: localhost:8080/es/createIndexWithMapping
创建成功后,验证索引:localhost:9200/hello ,返回值如下
字段解释
字段 | type | analyzer |
content | text | ik_max_word |
firstCode | keyword |
content字段的type是text,分词器是ik,表示这个字段会被分词,例如这个字段值是“中华人民共和国”,你搜索content字段可以模糊输入 共和国 、中华 都可以被搜到。
firstCode字段的type是 keyword,表示这是一个单词,不会被分词,例如这个字段值是“中华人民共和国”,那你输入共和国搜这个字段是搜不到的,属于精确查询才可以搜到
{
"hello":{
"aliases":{
},
"mappings":{
"properties":{
"_class":{
"type":"keyword",
"index":false,
"doc_values":false
},
"content":{
"type":"text",
"analyzer":"ik_max_word"
},
"firstCode":{
"type":"keyword"
},
"id":{
"type":"long"
},
"secordCode":{
"type":"keyword"
},
"type":{
"type":"integer"
}
}
},
"settings":{
"index":{
"refresh_interval":"1s",
"number_of_shards":"1",
"provided_name":"hello",
"creation_date":"1657701767667",
"store":{
"type":"fs"
},
"number_of_replicas":"1",
"uuid":"F6QnuExkSrKHcF_8NXcBtQ",
"version":{
"created":"7040099"
}
}
}
}
}
4.2 新增数据到索引
POST方式调用:http://localhost:8081/es
参数为:
{
"id": 1,
"firstCode": "小明",
"secordCode": "xiaoming",
"content": "中华人民共和国",
"type": 1
}
4.3 查询数据
GET方式调用:http://localhost:8081/es/1
返回值:
{
"content": "中华人民共和国",
"firstCode": "小明",
"id": 1,
"secordCode": "xiaoming",
"type": 1
}
4.4 修改数据
PUT方式调用:http://localhost:8081/es
{
"id": 1,
"firstCode": "小明小明小明",
"secordCode": "xm",
"content": "中华人民共和国",
"type": 2
}
再次查询ID 为1的数据
{
"content": "中华人民共和国",
"firstCode": "小明小明小明",
"id": 1,
"secordCode": "xm",
"type": 2
}
4.5 删除数据
DELETE方式调用:http://localhost:8081/es/1
4.6 模糊查询content字段,并高亮显示
GET方式调用:http://localhost:8081/es/findByContent?content=中华
返回结果:<em>标签包围的就是高亮显示
[
{
"content": {
"content": "中华人民共和国",
"id": 2
},
"highlightFields": {
"content": [
"<em>中华</em>人民共和国"
]
},
"id": "2",
"index": "hello",
"innerHits": {},
"matchedQueries": [],
"score": 0.13353139,
"sortValues": []
},
{
"content": {
"content": "中华人民共和国",
"firstCode": "小明小明小明",
"id": 1,
"secordCode": "xm",
"type": 2
},
"highlightFields": {
"content": [
"<em>中华</em>人民共和国"
]
},
"id": "1",
"index": "hello",
"innerHits": {},
"matchedQueries": [],
"score": 0.13353139,
"sortValues": []
}
]
5. 分词器、高亮显示
5.1 ik分词器指定
通过Field注解里面 analyzer指定ik分词器
ik分词类型 | 特点 |
ik_max_word | 一般用这个,例如中华人民共和国,拆分的词可能重复,拆分的更细致。 |
ik_smart | 拆分的词不会重复,拆分不是很细致 |
5.2 高亮显示
通过注解指定高亮显示的content
@Highlight(fields = {
@HighlightField(name = "content")
})
public interface HelloDao extends ElasticsearchRepository<HelloEntity, Long> {
/**
* 模糊查询content,高亮显示content
* @param content
* @return
*/
@Highlight(fields = {
@HighlightField(name = "content")
})
List<SearchHit<HelloEntity>> findByContent(String content);
}