5-8:开发社区搜索功能
生活随笔
收集整理的這篇文章主要介紹了
5-8:开发社区搜索功能
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
- 搜索服務(wù)
- 將帖子保存至Elasticsearch服務(wù)器。
- 從Elasticsearch服務(wù)器刪除帖子。
- 從Elasticsearch服務(wù)器搜索帖子。
- 發(fā)布事件
- 發(fā)布帖子時,將帖子異步的提交到Elasticsearch服務(wù)器。
- 增加評論時,將帖子異步的提交到Elasticsearch服務(wù)器。
- 在消費組件中增加一個方法,消費帖子發(fā)布事件。
- 顯示結(jié)果
- 在控制器中處理搜索請求,在HTML上顯示搜索結(jié)果。
歷史遺留問題:
在discusspost-mapper.xml中的方法
<insert id="insertDiscussPost" parameterType="DiscussPost" keyProperty="id"> insert into discuss_post(<include refid="insertFields"></include>) values(#{userId},#{title},#{content},#{type},#{status},#{createTime},#{commentCount},#{score}) </insert>
要添加keyProperty=“id”;
ElasticsearchService.java
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.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.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.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;@Service public class ElasticsearchService {@Autowiredprivate DiscussPostRepository discussRepository;@Autowiredprivate ElasticsearchTemplate elasticTemplate;//高亮顯示public void saveDiscussPost(DiscussPost post) {//向ES服務(wù)器存儲帖子discussRepository.save(post);}public void deleteDiscussPost(int id) {//刪除帖子,用到了帖子的iddiscussRepository.deleteById(id);}//提供的搜索方法,返回一個page類型的數(shù)據(jù)(spring提供的類型)public Page<DiscussPost> searchDiscussPost(String keyword, int current, int limit) {//支持分頁條件SearchQuery searchQuery = new NativeSearchQueryBuilder()//keyword查詢條件.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))//分頁條件,當前頁,從0開始,一頁多少條,注意顯示的過程.withHighlightFields(new HighlightBuilder.Field("title").preTags("<em>").postTags("</em>"),new HighlightBuilder.Field("content").preTags("<em>").postTags("</em>")).build();return 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));// 處理高亮顯示的結(jié)果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());}});}}DiscussPostController.java
修改發(fā)布帖子的方法
@RequestMapping(path = "/add", method = RequestMethod.POST)@ResponseBodypublic String addDiscussPost(String title, String content) {User user = hostHolder.getUser();if (user == null) {return CommunityUtil.getJSONString(403, "你還沒有登錄哦!");}DiscussPost post = new DiscussPost();post.setUserId(user.getId());post.setTitle(title);post.setContent(content);post.setCreateTime(new Date());discussPostService.addDiscussPost(post);// 觸發(fā)發(fā)帖事件,把新發(fā)布的帖子存到ES服務(wù)器里Event event = new Event().setTopic(TOPIC_PUBLISH)//在CommunityConstant 中定義了常量.setUserId(user.getId())//是誰觸發(fā)的事件,當前用戶.setEntityType(ENTITY_TYPE_POST).setEntityId(post.getId());eventProducer.fireEvent(event);// 報錯的情況,將來統(tǒng)一處理.return CommunityUtil.getJSONString(0, "發(fā)布成功!");}...CommentController .java
@RequestMapping(path = "/add/{discussPostId}", method = RequestMethod.POST)public String addComment(@PathVariable("discussPostId") int discussPostId, Comment comment) {comment.setUserId(hostHolder.getUser().getId());comment.setStatus(0);comment.setCreateTime(new Date());commentService.addComment(comment);// 觸發(fā)評論事件,對帖子的評論才觸發(fā)Event event = new Event().setTopic(TOPIC_COMMENT).setUserId(hostHolder.getUser().getId())//當前登錄用戶取值.setEntityType(comment.getEntityType()).setEntityId(comment.getEntityId()).setData("postId", discussPostId);if (comment.getEntityType() == ENTITY_TYPE_POST) {DiscussPost target = discussPostService.findDiscussPostById(comment.getEntityId());event.setEntityUserId(target.getUserId());} else if (comment.getEntityType() == ENTITY_TYPE_COMMENT) {Comment target = commentService.findCommentById(comment.getEntityId());event.setEntityUserId(target.getUserId());}eventProducer.fireEvent(event);if (comment.getEntityType() == ENTITY_TYPE_POST) {// 觸發(fā)發(fā)帖事件event = new Event().setTopic(TOPIC_PUBLISH).setUserId(comment.getUserId()).setEntityType(ENTITY_TYPE_POST).setEntityId(discussPostId);eventProducer.fireEvent(event);}return "redirect:/discuss/detail/" + discussPostId;}EventConsumer.java
消費發(fā)帖事件
DiscussPost post = discussPostService.findDiscussPostById(event.getEntityId());elasticsearchService.saveDiscussPost(post);//在服務(wù)器里存SearchController.java
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;@Controller public class SearchController implements CommunityConstant {@Autowiredprivate ElasticsearchService elasticsearchService;@Autowiredprivate UserService userService;@Autowiredprivate LikeService likeService;// search?keyword=xxx@RequestMapping(path = "/search", method = RequestMethod.GET)public String search(String keyword, Page page, Model model) {//傳入搜索的關(guān)鍵字// 搜索帖子org.springframework.data.domain.Page<DiscussPost> searchResult =//page.getCurrent() - 1方法是從0開始elasticsearchService.searchDiscussPost(keyword, page.getCurrent() - 1, page.getLimit());// 聚合數(shù)據(jù)List<Map<String, Object>> discussPosts = new ArrayList<>();if (searchResult != null) {for (DiscussPost post : searchResult) {Map<String, Object> map = new HashMap<>();// 帖子map.put("post", post);// 作者map.put("user", userService.findUserById(post.getUserId()));// 點贊數(shù)量map.put("likeCount", likeService.findEntityLikeCount(ENTITY_TYPE_POST, post.getId()));discussPosts.add(map);}}model.addAttribute("discussPosts", discussPosts);model.addAttribute("keyword", keyword);// 分頁信息page.setPath("/search?keyword=" + keyword);//設(shè)置顯示多少條數(shù)據(jù),若為空則沒有數(shù)據(jù),若有數(shù)據(jù)則設(shè)置page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements());return "/site/search";}處理搜索框的前端頁面
index.html
啟動即可
總結(jié)
以上是生活随笔為你收集整理的5-8:开发社区搜索功能的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 恢复数据U盘数据或磁盘无意删除的数据
- 下一篇: 即时通讯websocket原码下载