起因:在項(xiàng)目開(kāi)發(fā)過(guò)程中憎兽,要使用到搜索 引擎來(lái)對(duì)一些關(guān)鍵字實(shí)現(xiàn)逆向查詢(xún)撑蚌,如果僅用模糊搜索,那么搜索的時(shí)間會(huì)根據(jù)數(shù)據(jù)量的增大而增大刽肠,對(duì)比之下就學(xué)了elasticsearch溃肪,也記錄一下,常骋粑澹回顧惫撰。
1. Springboot整合Elasticsearch進(jìn)行索引操作
POM中增加依賴(lài)
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
yaml配置
# 端口一定要9300
spring:
data:
elasticsearch:
cluster-name: icoding-es
cluster-nodes: 47.92.163.109:9300
創(chuàng)建映射的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相當(dāng)于給索引明名
//type相當(dāng)于文檔類(lèi)型
@Data
@Document(indexName = "index_user",type = "_doc",shards = 3,replicas = 1)
public class UserBo {
//index的doc的id和數(shù)據(jù)的id一致
@Id
private String id;
//默認(rèn)不是存儲(chǔ)節(jié)點(diǎn),要聲明
@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;
}
創(chuàng)建索引的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 艾編程課程非常不錯(cuò)躺涝,學(xué)起來(lái)很給力");
userBo.setSex(1);
IndexQuery indexQuery = new IndexQueryBuilder()
.withObject(userBo)
.build();
elasticsearchTemplate.index(indexQuery);
return "index/mapping/document 一起創(chuàng)建完成";
}
}
更新索引的mapping
// 只需要在po里加上字段既可以
// 創(chuàng)建的時(shí)候給賦值
// 更新的時(shí)候elasticsearchTemplate會(huì)根據(jù)po的變化判斷是否更新
// 在elasticsearchTemplate.index(indexQuery)操作時(shí)如果沒(méi)有index則新建厨钻,如果有就創(chuàng)建數(shù)據(jù)
刪除index
@GetMapping("/delete-index")
@ResponseBody
public String deleteIndex(){
elasticsearchTemplate.deleteIndex(UserBo.class);
return "刪除成功";
}
ElasticsearchTemplate一般用于對(duì)文檔數(shù)據(jù)進(jìn)行檢索應(yīng)用
- 對(duì)于index的mapping還是使用json來(lái)創(chuàng)建
- ET的部分注解不一定生效
2. Springboot對(duì)ES文檔進(jìn)行操作
更新document
@GetMapping("/update")
@ResponseBody
public String updateIndex(){
Map<String,Object> data = new HashMap<String,Object>();
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;
}
根據(jù)id獲得doc數(shù)據(jù)
@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對(duì)ES文檔進(jìn)行分頁(yè)查詢(xún)
// ES中已有的index映射對(duì)象
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;
}
查詢(xún)分頁(yè)的controller
@GetMapping("/list")
@ResponseBody
public String getList(){
//3.定義分頁(yè)
Pageable pageable = PageRequest.of(0,2);
//2.定義query對(duì)象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾編程 學(xué)習(xí)"))
.withPageable(pageable)
.build();
//1.先寫(xiě)查詢(xún)
AggregatedPage<CustomerPo> customerPos = elasticsearchTemplate.queryForPage(query,CustomerPo.class);
System.out.println("總頁(yè)數(shù):"+customerPos.getTotalPages());
System.out.println("總記錄數(shù):"+customerPos.getTotalElements());
List<CustomerPo> customerPoList = customerPos.getContent();
for (CustomerPo customerPo:customerPoList) {
System.out.println(customerPo.toString());
}
return "查詢(xún)完成";
}
4. Springboot對(duì)ES文檔實(shí)現(xiàn)高亮查詢(xún)
//目前已加入高亮的字符,但會(huì)報(bào)錯(cuò)坚嗜,無(wú)法獲得值
@GetMapping("/listhiglight")
@ResponseBody
public String getListHighLight(){
//4.定義高亮的字符
String preTag = "<font color='red'>";
String postTag = "</font>";
//3.定義分頁(yè)
Pageable pageable = PageRequest.of(0,2);
//2.定義query對(duì)象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾編程 學(xué)習(xí)"))
.withHighlightFields(new HighlightBuilder.Field("desc").preTags(preTag).postTags(postTag))
.withPageable(pageable)
.build();
//1.先寫(xiě)查詢(xún),參數(shù)里增加高亮的實(shí)現(xiàn)
AggregatedPage<CustomerPo> customerPos = elasticsearchTemplate.queryForPage(query, CustomerPo.class, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
return null;
}
@Override
public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
return null;
}
});
System.out.println("總頁(yè)數(shù):"+customerPos.getTotalPages());
System.out.println("總記錄數(shù):"+customerPos.getTotalElements());
List<CustomerPo> customerPoList = customerPos.getContent();
for (CustomerPo customerPo:customerPoList) {
System.out.println(customerPo.toString());
}
return "查詢(xún)完成";
}
實(shí)現(xiàn)高亮完整代碼
@GetMapping("/listhiglight")
@ResponseBody
public String getListHighLight(){
//4.定義高亮的字符
String preTag = "<font color='red'>";
String postTag = "</font>";
//3.定義分頁(yè)
Pageable pageable = PageRequest.of(0,2);
//2.定義query對(duì)象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾編程 學(xué)習(xí)"))
.withHighlightFields(new HighlightBuilder.Field("desc").preTags(preTag).postTags(postTag))
.withPageable(pageable)
.build();
//1.先寫(xiě)查詢(xún),參數(shù)里增加高亮的實(shí)現(xiàn)
AggregatedPage<CustomerPo> customerPos = elasticsearchTemplate.queryForPage(query, CustomerPo.class, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
List<CustomerPo> customerPoList = new ArrayList<CustomerPo>();
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<T>) customerPoList);
}
return null;
}
@Override
public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
return null;
}
});
System.out.println("總頁(yè)數(shù):"+customerPos.getTotalPages());
System.out.println("總記錄數(shù):"+customerPos.getTotalElements());
List<CustomerPo> customerPoList = customerPos.getContent();
for (CustomerPo customerPo:customerPoList) {
System.out.println(customerPo.toString());
}
return "查詢(xún)完成";
}
5. Springboot對(duì)ES文檔進(jìn)行數(shù)據(jù)排序
只需要加入排序的構(gòu)建就ok了
@GetMapping("/list")
@ResponseBody
public String getList(){
//4.加入排序構(gòu)建
SortBuilder sortBuilder1 = new FieldSortBuilder("consume")
.order(SortOrder.DESC);
SortBuilder sortBuilder2 = new FieldSortBuilder("age")
.order(SortOrder.ASC);
//3.定義分頁(yè)
Pageable pageable = PageRequest.of(0,6);
//2.定義query對(duì)象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","學(xué)習(xí)"))
.withPageable(pageable)
.withSort(sortBuilder1)
.withSort(sortBuilder2)
.build();
//1.先寫(xiě)查詢(xún)
AggregatedPage<CustomerPo> customerPos = elasticsearchTemplate.queryForPage(query,CustomerPo.class);
System.out.println("總頁(yè)數(shù):"+customerPos.getTotalPages());
System.out.println("總記錄數(shù):"+customerPos.getTotalElements());
List<CustomerPo> customerPoList = customerPos.getContent();
for (CustomerPo customerPo:customerPoList) {
System.out.println(customerPo.toString());
}
return "查詢(xún)完成";
}
不要以為每天把功能完成了就行了夯膀,這種思想是要不得的,互勉~苍蔬!