起因:在项目开发过程中,要使用到搜索 引擎来对一些关键字实现逆向查询,如果仅用模糊搜索,那么搜索的时间会根据数据量的增大而增大,对比之下就学了elasticsearch,也记录一下,常常回顾。
1. Springboot整合Elasticsearch进行索引操作
POM中增加依赖
org.springframework.boot
spring-boot-starter-data-elasticsearch
yaml配置
# 端口一定要9300
spring:
data:
elasticsearch:
cluster-name: icoding-es
cluster-nodes: 47.92.163.109:9300
创建映射的po
package com.icodingedu.po;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
//indexName相当于给索引明名
//type相当于文档类型
@Data
@Document(indexName = "index_user",type = "_doc",shards = 3,replicas = 1)
public class UserBo {
//index的doc的id和数据的id一致
@Id
private String id;
//默认不是存储节点,要声明
@Field(store = true,index = true,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
private String nickname;
@Field(store = true)
private Integer sex;
@Field(store = true)
private Double consume;
@Field(store = true,index = true,analyzer = "ik_max_word",searchAnalyzer = "ik_max_word")
private String review;
}
创建索引的controller
package com.icodingedu.controller;
import com.icodingedu.po.UserBo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.IndexQuery;
import org.springframework.data.elasticsearch.core.query.IndexQueryBuilder;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ResponseBody;
@Controller
public class ESUserController {
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
@GetMapping("/create_index")
@ResponseBody
public String createIndex(){
UserBo userBo = new UserBo();
userBo.setId("1001");
userBo.setConsume(1899.66);
userBo.setNickname("空中雄鹰");
userBo.setReview("icoding edu 艾编程课程非常不错,学起来很给力");
userBo.setSex(1);
IndexQuery indexQuery = new IndexQueryBuilder()
.withObject(userBo)
.build();
elasticsearchTemplate.index(indexQuery);
return "index/mapping/document 一起创建完成";
}
}
更新索引的mapping
// 只需要在po里加上字段既可以
// 创建的时候给赋值
// 更新的时候elasticsearchTemplate会根据po的变化判断是否更新
// 在elasticsearchTemplate.index(indexQuery)操作时如果没有index则新建,如果有就创建数据
删除index
@GetMapping("/delete-index")
@ResponseBody
public String deleteIndex(){
elasticsearchTemplate.deleteIndex(UserBo.class);
return "删除成功";
}
ElasticsearchTemplate一般用于对文档数据进行检索应用
- 对于index的mapping还是使用json来创建
- ET的部分注解不一定生效
2. Springboot对ES文档进行操作
更新document
@GetMapping("/update")
@ResponseBody
public String updateIndex(){
Map data = new HashMap();
data.put("username","jackwang");
data.put("consume",7888.99);
IndexRequest indexRequest = new IndexRequest();
indexRequest.source(data);
UpdateQuery updateQuery = new UpdateQueryBuilder()
.withClass(UserBo.class)
.withId("1001")
.withIndexRequest(indexRequest)
.build();
elasticsearchTemplate.update(updateQuery);
return "更新成功";
}
删除document
@GetMapping("/delete/{id}")
@ResponseBody
public String deleteDocument(@PathVariable("id") String uid){
elasticsearchTemplate.delete(UserBo.class,uid);
return "删除id:"+uid;
}
根据id获得doc数据
@GetMapping("/get/{id}")
@ResponseBody
public String getIndex(@PathVariable("id") String uid){
GetQuery query = new GetQuery();
query.setId(uid);
UserBo userBo = elasticsearchTemplate.queryForObject(query,UserBo.class);
return userBo.toString();
}
3. Springboot对ES文档进行分页查询
// ES中已有的index映射对象
package com.icodingedu.po;
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
@Data
@Document(indexName = "index_customer",type = "_doc")
public class CustomerPo {
@Id
private String id;
@Field(store=true)
private Integer age;
@Field(store=true)
private String username;
@Field(store=true)
private String nickname;
@Field(store=true)
private Float consume;
@Field(store=true)
private String desc;
@Field(store=true)
private Integer sex;
@Field(store=true)
private String birthday;
@Field(store=true)
private String city;
@Field(store=true)
private String faceimg;
}
查询分页的controller
@GetMapping("/list")
@ResponseBody
public String getList(){
//3.定义分页
Pageable pageable = PageRequest.of(0,2);
//2.定义query对象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))
.withPageable(pageable)
.build();
//1.先写查询
AggregatedPage customerPos = elasticsearchTemplate.queryForPage(query,CustomerPo.class);
System.out.println("总页数:"+customerPos.getTotalPages());
System.out.println("总记录数:"+customerPos.getTotalElements());
List customerPoList = customerPos.getContent();
for (CustomerPo customerPo:customerPoList) {
System.out.println(customerPo.toString());
}
return "查询完成";
}
4. Springboot对ES文档实现高亮查询
//目前已加入高亮的字符,但会报错,无法获得值
@GetMapping("/listhiglight")
@ResponseBody
public String getListHighLight(){
//4.定义高亮的字符
String preTag = "";
String postTag = "";
//3.定义分页
Pageable pageable = PageRequest.of(0,2);
//2.定义query对象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))
.withHighlightFields(new HighlightBuilder.Field("desc").preTags(preTag).postTags(postTag))
.withPageable(pageable)
.build();
//1.先写查询,参数里增加高亮的实现
AggregatedPage customerPos = elasticsearchTemplate.queryForPage(query, CustomerPo.class, new SearchResultMapper() {
@Override
public AggregatedPage mapResults(SearchResponse searchResponse, Class aClass, Pageable pageable) {
return null;
}
@Override
public T mapSearchHit(SearchHit searchHit, Class aClass) {
return null;
}
});
System.out.println("总页数:"+customerPos.getTotalPages());
System.out.println("总记录数:"+customerPos.getTotalElements());
List customerPoList = customerPos.getContent();
for (CustomerPo customerPo:customerPoList) {
System.out.println(customerPo.toString());
}
return "查询完成";
}
实现高亮完整代码
@GetMapping("/listhiglight")
@ResponseBody
public String getListHighLight(){
//4.定义高亮的字符
String preTag = "";
String postTag = "";
//3.定义分页
Pageable pageable = PageRequest.of(0,2);
//2.定义query对象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))
.withHighlightFields(new HighlightBuilder.Field("desc").preTags(preTag).postTags(postTag))
.withPageable(pageable)
.build();
//1.先写查询,参数里增加高亮的实现
AggregatedPage customerPos = elasticsearchTemplate.queryForPage(query, CustomerPo.class, new SearchResultMapper() {
@Override
public AggregatedPage mapResults(SearchResponse searchResponse, Class aClass, Pageable pageable) {
List customerPoList = new ArrayList();
SearchHits searchHits = searchResponse.getHits();
for (SearchHit h: searchHits) {
HighlightField highlightField = h.getHighlightFields().get("desc");
String desc = highlightField.fragments()[0].toString();
CustomerPo customerPoHighlight = new CustomerPo();
customerPoHighlight.setAge((Integer)h.getSourceAsMap().get("age"));
customerPoHighlight.setBirthday(h.getSourceAsMap().get("birthday").toString());
customerPoHighlight.setCity(h.getSourceAsMap().get("city").toString());
customerPoHighlight.setConsume(Float.valueOf(h.getSourceAsMap().get("consume").toString()));
customerPoHighlight.setDesc(desc);//这就是把高亮的字段替换给原字段
customerPoHighlight.setFaceimg(h.getSourceAsMap().get("faceimg").toString());
customerPoHighlight.setId(h.getSourceAsMap().get("id").toString());
customerPoHighlight.setNickname(h.getSourceAsMap().get("nickname").toString());
customerPoHighlight.setSex((Integer)h.getSourceAsMap().get("sex"));
customerPoHighlight.setUsername(h.getSourceAsMap().get("username").toString());
customerPoList.add(customerPoHighlight);
}
if(customerPoList.size()>0){
return new AggregatedPageImpl<>((List) customerPoList);
}
return null;
}
@Override
public T mapSearchHit(SearchHit searchHit, Class aClass) {
return null;
}
});
System.out.println("总页数:"+customerPos.getTotalPages());
System.out.println("总记录数:"+customerPos.getTotalElements());
List customerPoList = customerPos.getContent();
for (CustomerPo customerPo:customerPoList) {
System.out.println(customerPo.toString());
}
return "查询完成";
}
5. Springboot对ES文档进行数据排序
只需要加入排序的构建就ok了
@GetMapping("/list")
@ResponseBody
public String getList(){
//4.加入排序构建
SortBuilder sortBuilder1 = new FieldSortBuilder("consume")
.order(SortOrder.DESC);
SortBuilder sortBuilder2 = new FieldSortBuilder("age")
.order(SortOrder.ASC);
//3.定义分页
Pageable pageable = PageRequest.of(0,6);
//2.定义query对象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","学习"))
.withPageable(pageable)
.withSort(sortBuilder1)
.withSort(sortBuilder2)
.build();
//1.先写查询
AggregatedPage customerPos = elasticsearchTemplate.queryForPage(query,CustomerPo.class);
System.out.println("总页数:"+customerPos.getTotalPages());
System.out.println("总记录数:"+customerPos.getTotalElements());
List customerPoList = customerPos.getContent();
for (CustomerPo customerPo:customerPoList) {
System.out.println(customerPo.toString());
}
return "查询完成";
}
不要以为每天把功能完成了就行了,这种思想是要不得的,互勉~!