data:elasticsearch:cluster-name: nowcodercluster-nodes: 127.0.0.1:9300
需要在你要加入es中的实体上添加注解:
package com.nowcoder.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;//设置索引名字 类型(6.x以后可能废弃给个死值) shards 分片(每个索引可以分为多个分片以提高性能)
//replicas 副本(每个索引的备份)
@Document(indexName = "discusspost", type = "_doc", shards = 6, replicas = 3)
public class DiscussPost {@Idprivate 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;}@Overridepublic String toString() {return "DiscussPost{" +"id=" + id +", userId=" + userId +", title='" + title + '\'' +", content='" + content + '\'' +", type=" + type +", status=" + status +", createTime=" + createTime +", commentCount=" + commentCount +", score=" + score +'}';}
}
Repository:
package com.nowcoder.community.dao.elasticsearch;import com.nowcoder.community.entity.DiscussPost;
import org.springframework.data.elasticsearch.repository.ElasticsearchRepository;
import org.springframework.stereotype.Repository;/*** @Description* @Author Mr.Dong <dongcf1997@163.com>* @Version V1.0.0* @Since 1.0* @Date 2021/3/22 13:49*/
@Repository
public interface DiscusspostRepository extends ElasticsearchRepository<DiscussPost,Integer> {
}
service层:
package com.nowcoder.community.service;import com.nowcoder.community.dao.elasticsearch.DiscusspostRepository;
import com.nowcoder.community.entity.DiscussPost;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortBuilder;
import org.elasticsearch.search.sort.SortBuilders;
import org.elasticsearch.search.sort.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.stereotype.Service;import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @Description* @Author Mr.Dong <dongcf1997@163.com>* @Version V1.0.0* @Since 1.0* @Date 2021/3/22 20:13*/
@Service
public class ElasticsearchService {@Autowiredprivate DiscusspostRepository discusspostRepository;@Autowiredprivate ElasticsearchTemplate elasticsearchTemplate;public void saveDiscussPost(DiscussPost discussPost) {discusspostRepository.save(discussPost);}public void deleteDiscussPost(int id) {discusspostRepository.deleteById(id);}public Page<DiscussPost> searchDiscussPost(String keyword, Integer current, Integer limit) {SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.multiMatchQuery(keyword, "title", "content")).withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)).withPageable(PageRequest.of(current, limit)).withHighlightFields(new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")).build();return elasticsearchTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {@Overridepublic <T> AggregatedPage<T> mapResults(SearchResponse searchResponse, Class<T> aClass, Pageable pageable) {SearchHits hits = searchResponse.getHits();if (hits.getTotalHits() <= 0) {return null;}List<DiscussPost> list = new ArrayList<>();for (SearchHit hit : hits) {DiscussPost post = new DiscussPost();String id = hit.getSourceAsMap().get("id").toString();post.setId(Integer.valueOf(id));String userId = hit.getSourceAsMap().get("userId").toString();post.setUserId(Integer.valueOf(userId));String title = hit.getSourceAsMap().get("title").toString();post.setTitle(title);String content = hit.getSourceAsMap().get("content").toString();post.setContent(content);String status = hit.getSourceAsMap().get("status").toString();post.setStatus(Integer.valueOf(status));String createTime = hit.getSourceAsMap().get("createTime").toString();post.setCreateTime(new Date(Long.valueOf(createTime)));String commentCount = hit.getSourceAsMap().get("commentCount").toString();post.setCommentCount(Integer.valueOf(commentCount));// 处理高亮显示的结果HighlightField titleField = hit.getHighlightFields().get("title");if (titleField != null) {post.setTitle(titleField.getFragments()[0].toString());}HighlightField contentField = hit.getHighlightFields().get("content");if (contentField != null) {post.setContent(contentField.getFragments()[0].toString());}list.add(post);}return new AggregatedPageImpl(list, pageable,hits.getTotalHits(), searchResponse.getAggregations(), searchResponse.getScrollId(), hits.getMaxScore());}});}}
controller:
package com.nowcoder.community.controller;import com.nowcoder.community.entity.DiscussPost;
import com.nowcoder.community.entity.Page;
import com.nowcoder.community.service.ElasticsearchService;
import com.nowcoder.community.service.LikeService;
import com.nowcoder.community.service.UserService;
import com.nowcoder.community.util.CommunityConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;/*** @Description* @Author Mr.Dong <dongcf1997@163.com>* @Version V1.0.0* @Since 1.0* @Date 2021/3/22 22:09*/
@Controller
public class SearchController implements CommunityConstant {@Autowiredprivate ElasticsearchService elasticsearchService;@Autowiredprivate UserService userService;@Autowiredprivate LikeService likeService;@RequestMapping(path = "/search",method = RequestMethod.GET)public String search(String keyword, Page page, Model model){org.springframework.data.domain.Page<DiscussPost> discussPosts = elasticsearchService.searchDiscussPost(keyword, page.getCurrent()-1, page.getLimit());if(discussPosts==null){model.addAttribute("discussPosts",null);return "/site/search";}List<Map<String,Object>> list = new ArrayList<>();for (DiscussPost discussPost: discussPosts) {Map<String,Object> map = new HashMap<>();map.put("post",discussPost);//作者map.put("user",userService.findUserById(discussPost.getUserId()));//点赞数量map.put("likeCount",likeService.findEntityLikeCount(ENTITY_TYPE_POST,discussPost.getId()));list.add(map);}model.addAttribute("discussPosts",list);model.addAttribute("keyword",keyword);page.setPath("/search?keyword="+keyword);page.setRows(discussPosts == null ? 0: (int) discussPosts.getTotalElements());return "/site/search";}}
tests:
package com.nowcoder.community;import com.nowcoder.community.dao.DiscussPostMapper;
import com.nowcoder.community.dao.elasticsearch.DiscussPostRepository;
import com.nowcoder.community.entity.DiscussPost;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.SearchHits;
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.boot.test.context.SpringBootTest;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
import org.springframework.data.elasticsearch.core.SearchResultMapper;
import org.springframework.data.elasticsearch.core.aggregation.AggregatedPage;
import org.springframework.data.elasticsearch.core.aggregation.impl.AggregatedPageImpl;
import org.springframework.data.elasticsearch.core.query.NativeSearchQueryBuilder;
import org.springframework.data.elasticsearch.core.query.SearchQuery;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringRunner;import java.util.ArrayList;
import java.util.Date;
import java.util.List;@RunWith(SpringRunner.class)
@SpringBootTest
@ContextConfiguration(classes = CommunityApplication.class)
public class ElasticsearchTests {@Autowiredprivate DiscussPostMapper discussMapper;@Autowiredprivate DiscussPostRepository discussRepository;@Autowiredprivate ElasticsearchTemplate elasticTemplate;@Testpublic void testInsert() {discussRepository.save(discussMapper.selectDiscussPostById(241));discussRepository.save(discussMapper.selectDiscussPostById(242));discussRepository.save(discussMapper.selectDiscussPostById(243));}@Testpublic void testInsertList() {discussRepository.saveAll(discussMapper.selectDiscussPosts(101, 0, 100, 0));discussRepository.saveAll(discussMapper.selectDiscussPosts(102, 0, 100, 0));discussRepository.saveAll(discussMapper.selectDiscussPosts(103, 0, 100, 0));discussRepository.saveAll(discussMapper.selectDiscussPosts(111, 0, 100, 0));discussRepository.saveAll(discussMapper.selectDiscussPosts(112, 0, 100, 0));discussRepository.saveAll(discussMapper.selectDiscussPosts(131, 0, 100, 0));discussRepository.saveAll(discussMapper.selectDiscussPosts(132, 0, 100, 0));discussRepository.saveAll(discussMapper.selectDiscussPosts(133, 0, 100, 0));discussRepository.saveAll(discussMapper.selectDiscussPosts(134, 0, 100, 0));}@Testpublic void testUpdate() {DiscussPost post = discussMapper.selectDiscussPostById(231);post.setContent("我是新人,使劲灌水.");discussRepository.save(post);}@Testpublic void testDelete() {// discussRepository.deleteById(231);discussRepository.deleteAll();}@Testpublic void testSearchByRepository() {SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content")).withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)).withPageable(PageRequest.of(0, 10)).withHighlightFields(new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")).build();// elasticTemplate.queryForPage(searchQuery, class, SearchResultMapper)// 底层获取得到了高亮显示的值, 但是没有返回.Page<DiscussPost> page = discussRepository.search(searchQuery);System.out.println(page.getTotalElements());System.out.println(page.getTotalPages());System.out.println(page.getNumber());System.out.println(page.getSize());for (DiscussPost post : page) {System.out.println(post);}}@Testpublic void testSearchByTemplate() {SearchQuery searchQuery = new NativeSearchQueryBuilder().withQuery(QueryBuilders.multiMatchQuery("互联网寒冬", "title", "content")).withSort(SortBuilders.fieldSort("type").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("score").order(SortOrder.DESC)).withSort(SortBuilders.fieldSort("createTime").order(SortOrder.DESC)).withPageable(PageRequest.of(0, 10)).withHighlightFields(new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")).build();Page<DiscussPost> page = elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {@Overridepublic <T> AggregatedPage<T> mapResults(SearchResponse response, Class<T> aClass, Pageable pageable) {SearchHits hits = response.getHits();if (hits.getTotalHits() <= 0) {return null;}List<DiscussPost> list = new ArrayList<>();for (SearchHit hit : hits) {DiscussPost post = new DiscussPost();String id = hit.getSourceAsMap().get("id").toString();post.setId(Integer.valueOf(id));String userId = hit.getSourceAsMap().get("userId").toString();post.setUserId(Integer.valueOf(userId));String title = hit.getSourceAsMap().get("title").toString();post.setTitle(title);String content = hit.getSourceAsMap().get("content").toString();post.setContent(content);String status = hit.getSourceAsMap().get("status").toString();post.setStatus(Integer.valueOf(status));String createTime = hit.getSourceAsMap().get("createTime").toString();post.setCreateTime(new Date(Long.valueOf(createTime)));String commentCount = hit.getSourceAsMap().get("commentCount").toString();post.setCommentCount(Integer.valueOf(commentCount));// 处理高亮显示的结果HighlightField titleField = hit.getHighlightFields().get("title");if (titleField != null) {post.setTitle(titleField.getFragments()[0].toString());}HighlightField contentField = hit.getHighlightFields().get("content");if (contentField != null) {post.setContent(contentField.getFragments()[0].toString());}list.add(post);}return new AggregatedPageImpl(list, pageable,hits.getTotalHits(), response.getAggregations(), response.getScrollId(), hits.getMaxScore());}});System.out.println(page.getTotalElements());System.out.println(page.getTotalPages());System.out.println(page.getNumber());System.out.println(page.getSize());for (DiscussPost post : page) {System.out.println(post);}}}