ElasticSearch整合Springboot
注意springboot版本2.2.5 适配es7.5
1. ElasticSearch整合Springboot文件配置
可以直接导入springboot的ES的POM依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-elasticsearch</artifactId>
</dependency>
ymal的配置
spring:
application:
name: imall-elasticsearch
data:
elasticsearch:
cluster-name: icoding-es
cluster-nodes: 39.100.237.146:9200
spring.data.elasticsearch.cluster-nodes=127.0.0.1:9200
#spring.data.elasticsearch.cluster-nodes=127.0.0.1:9200,ip1:9300,ip2:9200
spring.data.elasticsearch.cluster-name=docker-cluster
2. 索引操作
-
使用elasticsearchTemplate创建index时,分片及field类型和相关设置有一定问题
-
即便是注解说明了也不一定生效,不灵活
创建索引的映射对象
创建实体类 用程序方式创建索引(不建议一般收动创建)
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
@Data
@Document(indexName = "index_user",type="_doc",replicas = 1,shards = 5)
public class UserBo {
//index的id和数据id保持一致
@Id
private String id;
@Field(store = true,type = FieldType.Text,analyzer = "ik_smart",searchAnalyzer ="ik_smart")
private String username;
@Field(store = true,type = FieldType.Text,analyzer = "ik_smart",searchAnalyzer ="ik_smart")
private String nickname;
@Field(store = true,type = FieldType.Integer)
private Integer sex;
@Field(store = true,type = FieldType.Double)
private Double consume;
@Field(store = true,type=FieldType.Keyword)
private String review;
}
@Repository //有这个类会自动创建索引
public interface UserBoDao extends ElasticsearchRepository<UserBo,Long>{}
3.基本文档API使用
- Controller
import com.springcloud.esboot.pojo.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.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
public class ESTestController {
@Autowired
ElasticsearchTemplate elasticsearchTemplate;
@GetMapping("createindex")
public String createIndex(){
UserBo userBo = new UserBo();
userBo.setId("1001");
userBo.setConsume(1899.89);
userBo.setNickname("空中雄鹰");
userBo.setReview("icodingedu的课程还不错,学习起来很给力");
userBo.setSex(1);
IndexQuery indexQuery = new IndexQueryBuilder().withObject(userBo).build();
//构建索引并创建mapping和document
elasticsearchTemplate.index(indexQuery);
return "添加数据";
}
//更新数据和索引
@GetMapping("updateMapping")
public String updateMapping(){
UserBo userBo = new UserBo();
userBo.setId("1002");
userBo.setConsume(1899.89);
//更新操作UserBo添加字段
// @Field(store = true,type = FieldType.Text,analyzer = "ik_smart",searchAnalyzer ="ik_smart")
// private String username;
userBo.setUsername("上天入地");
userBo.setNickname("空中雄鹰");
userBo.setReview("icodingedu的课程还不错,学习起来很给力");
userBo.setSex(1);
IndexQuery indexQuery = new IndexQueryBuilder().withObject(userBo).build();
//构建索引并创建mapping和document
elasticsearchTemplate.index(indexQuery);
return "success";
}
//删除索引 表
@GetMapping("delindex")
public String delindex(){
elasticsearchTemplate.deleteIndex("mk_content");
//方法2
// elasticsearchTemplate.deleteIndex(UserBo.class);
return "success";
}
}
具体报错如下:
failed to load elasticsearch nodes : org.elasticsearch.client.transport.NoNodeAvailableException: None of the configured nodes are available: [{#transport#-1}{m-smEJI0TKOTPDV_eVS1hQ}{127.0.0.1}{127.0.0.1:9300}]
原因如下:
首先我的elasticsearch版本是elasticsearch 7.x,我的SpringBoot版本是2.1.8,注意:SpringBoot是2.2.0.RELEASE才兼容elasticsearch 7.x
解决如下:
方式一:升级springboot到2.2.0及以上
方式二:降低elasticsearch版本到自己项目中对于jar的版本
————————————————
版权声明:本文为优快云博主「NPException」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.youkuaiyun.com/qq_36850813/article/details/103205037
4. 对文档进行操作
4.1使用Dao操作
// 其实就是动态代理来完成
@Repository
public interface ContentDao extends ElasticsearchRepository<Content,Long> {
}
@Override
public Content saveContent(Content content) {
return contentDao.save(content);
}
public Object searchContent(String keyword){
// 建立搜索条件
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(keyword).defaultField("title");
Iterable<Content> search1 = contentDao.search(queryStringQueryBuilder);
return search1;
}
public Page<Content> searchContentPage(String keyword,int pageNo,int pageSize){
if(pageNo<=1)pageNo = 1;
//设置分页信息
PageRequest pageRequest = PageRequest.of(pageNo-1, pageSize); // 建立搜索条件
QueryStringQueryBuilder queryStringQueryBuilder = QueryBuilders.queryStringQuery(keyword).defaultField("title");
// 根据搜索条件和分页信息,返回内容
Page<Content> search = contentDao.search(queryStringQueryBuilder, pageRequest);
return search;
}
4.2使用Template中各种操作
基础操作
@GetMapping("update")
public String updateIndex(){
//4.写入要修改的值
Map<String,Object> data = new HashMap<>();
data.put("username","gavin.huang");
data.put("nickname","我是艾编程老师");
data.put("consume",59999.99);
//3.写请求数据
IndexRequest indexRequest = new IndexRequest();
indexRequest.source(data);
//2.定义更新对象
UpdateQuery updateQuery = new UpdateQueryBuilder()
.withClass(UserBo.class).withId("1002")
.withIndexRequest(indexRequest)
.build();
//1.先写update 方法
elasticsearchTemplate.update(updateQuery);
return "修改成功";
}
@GetMapping("/get/{id}")
public String getIndex(@PathVariable("id") String uid){
GetQuery query = new GetQuery();
query.setId(uid);
UserBo userBo = elasticsearchTemplate.queryForObject(query,UserBo.class);
return userBo.toString();
}
@GetMapping("/deldoc/{id}")
public String deleteDocument(@PathVariable("id") String uid){
elasticsearchTemplate.delete(UserBo.class,uid);
return "删除id:"+uid;
}
实现分页搜索
使用之前创建的index_customer测试
import lombok.Data;
import org.springframework.data.annotation.Id;
import org.springframework.data.elasticsearch.annotations.Document;
import org.springframework.data.elasticsearch.annotations.Field;
import org.springframework.data.elasticsearch.annotations.FieldType;
@Data
@Document(indexName = "index_customer",type = "_doc")
public class CustomerBo {
@Id
private Integer 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;
}
@GetMapping("list")
public String getList(){
//3.增加分页对象
Pageable pageable = PageRequest.of(0,2);
//2.定义query对象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))//空格拆分分词
// .withFields("id","nickname","desc") //指定返回的具体列
.withPageable(pageable) //设置分页参数
.build();
//1.查询语句
AggregatedPage<CustomerBo> customerPages = elasticsearchTemplate.queryForPage(query,CustomerBo.class);
System.out.println("总页数:"+customerPages.getTotalPages());
System.out.println("总记录数:"+customerPages.getTotalElements());
List<CustomerBo> customerBoList = customerPages.getContent();
for (CustomerBo customerBo:customerBoList) {
System.out.println(customerBo);
}
return "查询完成.....";
}
查询结果高亮
@GetMapping("listhighlight")
public String getListHighLight(){
String preTag = "<font color='red'>";
String postTag = "</font>";
Pageable pageable = PageRequest.of(1,3);
//2.定义query对象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))
.withPageable(pageable)
.withHighlightFields(new HighlightBuilder.Field("desc").preTags(preTag).postTags(postTag))
.build();
//1.先写查询
AggregatedPage<CustomerBo> customerPages = elasticsearchTemplate.queryForPage(query, CustomerBo.class, new SearchResultMapper() {
@Override
public <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {
List<CustomerBo> customerHighLightList = new ArrayList<>();
SearchHits searchHits = searchResponse.getHits();//获取命中结果
for (SearchHit h : searchHits) {
HighlightField highlightField = h.getHighlightFields().get("desc");//获取高亮设置的列
String desc = highlightField.fragments()[0].toString();//拿到高亮的值
CustomerBo customerHighLight = new CustomerBo();
customerHighLight.setAge((Integer)h.getSourceAsMap().get("age"));
customerHighLight.setBirthday(h.getSourceAsMap().get("birthday").toString());
customerHighLight.setCity(h.getSourceAsMap().get("city").toString());
customerHighLight.setConsume(Float.valueOf(h.getSourceAsMap().get("consume").toString()));
customerHighLight.setDesc(desc);
customerHighLight.setFaceimg(h.getSourceAsMap().get("faceimg").toString());
customerHighLight.setId((Integer)h.getSourceAsMap().get("id"));
customerHighLight.setNickname(h.getSourceAsMap().get("nickname").toString());
customerHighLight.setSex((Integer)h.getSourceAsMap().get("sex"));
customerHighLight.setUsername(h.getSourceAsMap().get("username").toString());
customerHighLightList.add(customerHighLight);//将查询的实体对象放入返回结果集中
}
if(customerHighLightList.size()>0){
return new AggregatedPageImpl<>((List<T>)customerHighLightList,pageable,searchResponse.getHits().getTotalHits());
}
return null;
}
@Override
public <T> T mapSearchHit(SearchHit searchHit, Class<T> aClass) {
return null;
}
});
System.out.println("总页数:"+customerPages.getTotalPages());
System.out.println("总记录数:"+customerPages.getTotalElements());
List<CustomerBo> customerBoList = customerPages.getContent();
for (CustomerBo customerBo:customerBoList) {
System.out.println(customerBo);
}
return "查询完成.....";
}
结果排序
@GetMapping("list2")
public String getList2(){
//4.增加排序对象
SortBuilder sortConsume = new FieldSortBuilder("consume").order(SortOrder.DESC);
SortBuilder sortAge = new FieldSortBuilder("age").order(SortOrder.ASC);
//3.增加分页对象
Pageable pageable = PageRequest.of(0,6);
//2.定义query对象
SearchQuery query = new NativeSearchQueryBuilder()
.withQuery(QueryBuilders.matchQuery("desc","艾编程 学习"))
//.withFields("id","nickname","desc") //指定返回的具体列
.withPageable(pageable) //设置分页参数
.withSort(sortConsume)
.withSort(sortAge)
.build();
//1.查询语句
AggregatedPage<CustomerBo> customerPages = elasticsearchTemplate.queryForPage(query,CustomerBo.class);
System.out.println("总页数:"+customerPages.getTotalPages());
System.out.println("总记录数:"+customerPages.getTotalElements());
List<CustomerBo> customerBoList = customerPages.getContent();
for (CustomerBo customerBo:customerBoList) {
System.out.println(customerBo);
}
return "查询完成.....";
}