Spring整合Elasticsearch
1.dao层
创建elasticsearch文件夹,添加DiscussPostRepository类。
package com.gerrard.community.dao.elasticsearch;
import com.gerrard.community.entity.DiscussPost;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;
@Repository //存储的实体类,主键什么类型
public interface DiscussPostRepository extends ElasticsearchRepository<DiscussPost,Integer> {
}
2.实体类改写
在DiscussPost实体类中添加与es相关的注解。
package com.gerrard.community.entity;
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;
import java.util.Date;
//@Document(indexName = "discusspost",type="_doc",shards = 6,replicas=3)
@Document(indexName = "discusspost",shards = 6,replicas=3)
public class DiscussPost {
@Id
private int id;
@Field(type= FieldType.Integer)
private int userId;
@Field(type=FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
private String title;
@Field(type=FieldType.Text,analyzer = "ik_max_word",searchAnalyzer = "ik_smart")
private String content;
@Field(type = FieldType.Integer)
private int type;
@Field(type = FieldType.Integer)
private int status;
@Field(type = FieldType.Date)
private Date createTime;
@Field(type = FieldType.Integer)
private int commentCount;
@Field(type = FieldType.Double)
private double score;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public int getUserId() {
return userId;
}
public void setUserId(int userId) {
this.userId = userId;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public String getContent() {
return content;
}
public void setContent(String content) {
this.content = content;
}
public int getType() {
return type;
}
public void setType(int type) {
this.type = type;
}
public int getStatus() {
return status;
}
public void setStatus(int status) {
this.status = status;
}
public Date getCreateTime() {
return createTime;
}
public void setCreateTime(Date createTime) {
this.createTime = createTime;
}
public int getCommentCount() {
return commentCount;
}
public void setCommentCount(int commentCount) {
this.commentCount = commentCount;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
@Override
public String toString() {
return "DiscussPost{" +
"id=" + id +
", userId=" + userId +
", title='" + title + '\'' +
", content='" + content + '\'' +
", type=" + type +
", status=" + status +
", createTime=" + createTime +
", commentCount=" + commentCount +
", score=" + score +
'}';
}
}
此外,还需在CommunityApplication类中设置不进行netty检查。
package com.gerrard.community;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import javax.annotation.PostConstruct;
@SpringBootApplication
public class CommunityApplication {
@PostConstruct
public void init() {
// 解决netty启动冲突问题
// see Netty4Utils.setAvailableProcessors()
System.setProperty("es.set.netty.runtime.available.processors", "false");
}
public static void main(String[] args) {
SpringApplication.run(CommunityApplication.class, args);
}
}
3.config包
添加EsConfig类。
package com.gerrard.community.config;
import org.elasticsearch.client.RestClient;
import org.elasticsearch.client.RestHighLevelClient;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.elasticsearch.client.ClientConfiguration;
import org.springframework.data.elasticsearch.client.RestClients;
@Configuration
public class EsConfig {
@Value("${elasticSearch.url}")
private String esUrl;
//localhost:9200,写在配置文件中就可以了
@Bean
RestHighLevelClient client(){
ClientConfiguration clientConfiguration=ClientConfiguration.builder()
.connectedTo(esUrl) //es地址
.build();
return RestClients.create(clientConfiguration).rest();
}
}
4.添加测试方法
添加ElasticsearchTests测试方法。
package com.gerrard.community;
import com.alibaba.fastjson.JSONObject;
import com.gerrard.community.dao.DiscussPostMapper;
import com.gerrard.community.dao.elasticsearch.DiscussPostRepository;
import com.gerrard.community.entity.DiscussPost;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.elasticsearch.client.elc.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;
import java.io.IOException;
import java.util.LinkedList;
import java.util.List;
@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class ElasticsearchTests {
@Autowired
private DiscussPostMapper discussMapper;
@Autowired
private DiscussPostRepository discussRepository;
// @Autowired
// private ElasticsearchTemplate elasticsearchTemplate;
@Qualifier("client")
@Autowired
private RestHighLevelClient restHighLevelClient;
@Test
public void testInsert(){
discussRepository.save(discussMapper.selectDiscussPostById(241));
discussRepository.save(discussMapper.selectDiscussPostById(242));
discussRepository.save(discussMapper.selectDiscussPostById(243));
}
// @Test
// public void testInsertList() {
// discussRepository.saveAll(discussMapper.selectDiscussPosts(101, 0, 100));
// discussRepository.saveAll(discussMapper.selectDiscussPosts(102, 0, 100));
// discussRepository.saveAll(discussMapper.selectDiscussPosts(103, 0, 100));
// discussRepository.saveAll(discussMapper.selectDiscussPosts(111, 0, 100));
// discussRepository.saveAll(discussMapper.selectDiscussPosts(112, 0, 100));
// discussRepository.saveAll(discussMapper.selectDiscussPosts(131, 0, 100));
// discussRepository.saveAll(discussMapper.selectDiscussPosts(132, 0, 100));
// discussRepository.saveAll(discussMapper.selectDiscussPosts(133, 0, 100));
// discussRepository.saveAll(discussMapper.selectDiscussPosts(134, 0, 100));
// }
@Test
public void testUpdate() {
DiscussPost post = discussMapper.selectDiscussPostById(231);
post.setContent("我是新人,使劲灌水.");
discussRepository.save(post);
}
@Test
public void testDelete() {
// discussRepository.deleteById(231);
discussRepository.deleteAll();
}
//不带高亮的查询
@Test
public void noHighlightQuery() throws IOException {
SearchRequest searchRequest = new SearchRequest("discusspost");//discusspost是索引名,就是表名
//构建搜索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
//在discusspost索引的title和content字段中都查询“互联网寒冬”
.query(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content"))
// matchQuery是模糊查询,会对key进行分词:searchSourceBuilder.query(QueryBuilders.matchQuery(key,value));
// termQuery是精准查询:searchSourceBuilder.query(QueryBuilders.termQuery(key,value));
.sort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
.sort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
.sort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
//一个可选项,用于控制允许搜索的时间:searchSourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));
.from(0)// 指定从哪条开始查询
.size(10);// 需要查出的总记录条数
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
System.out.println(JSONObject.toJSON(searchResponse));
List<DiscussPost> list = new LinkedList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
DiscussPost discussPost = JSONObject.parseObject(hit.getSourceAsString(), DiscussPost.class);
System.out.println(discussPost);
list.add(discussPost);
}
}
//带高亮的查询
@Test
public void highlightQuery() throws Exception{
SearchRequest searchRequest = new SearchRequest("discusspost");//discusspost是索引名,就是表名
//高亮
HighlightBuilder highlightBuilder = new HighlightBuilder();
highlightBuilder.field("title");
highlightBuilder.field("content");
highlightBuilder.requireFieldMatch(false);
highlightBuilder.preTags("<span style='color:red'>");
highlightBuilder.postTags("</span>");
//构建搜索条件
SearchSourceBuilder searchSourceBuilder = new SearchSourceBuilder()
.query(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content"))
.sort(SortBuilders.fieldSort("type").order(SortOrder.DESC))
.sort(SortBuilders.fieldSort("score").order(SortOrder.DESC))
.sort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC))
.from(0)// 指定从哪条开始查询
.size(10)// 需要查出的总记录条数
.highlighter(highlightBuilder);//高亮
searchRequest.source(searchSourceBuilder);
SearchResponse searchResponse = restHighLevelClient.search(searchRequest, RequestOptions.DEFAULT);
List<DiscussPost> list = new LinkedList<>();
for (SearchHit hit : searchResponse.getHits().getHits()) {
DiscussPost discussPost = JSONObject.parseObject(hit.getSourceAsString(), DiscussPost.class);
// 处理高亮显示的结果
HighlightField titleField = hit.getHighlightFields().get("title");
if (titleField != null) {
discussPost.setTitle(titleField.getFragments()[0].toString());
}
HighlightField contentField = hit.getHighlightFields().get("content");
if (contentField != null) {
discussPost.setContent(contentField.getFragments()[0].toString());
}
System.out.println(discussPost);
list.add(discussPost);
}
}
}
5.测试结果
运行noHighlightQuery方法:
运行highlightQuery()方法: