其他分享
首页 > 其他分享> > 论坛项目进展06

论坛项目进展06

作者:互联网

第6章 Elasticsearch,分布式搜索引擎
6.1 Elasticsearch入门

image-20220620181139084

6.2 Spring整合Elasticsearch

image-20220620182555051

把数据库里的帖子存到es服务器里,然后从es服务器里去搜索.

在DiscussPost实例类上加上:

@Document(indexName = "discusspost", type = "_doc", shards = 6, replicas = 3)//会自动将实体数据和es服务器里面的索引做映射,discusspost是索引名,shards为分片,分6片。replicas表示副本,备份三份。
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;
   。。。。。
}

访问es和访问mysql不一样,所以在dao包下建一个子包elasticsearch,在其下建DiscussPostRepository:

@Repository
public interface DiscussPostRepository extends ElasticsearchRepository<DiscussPost, Integer> {

}
6.3 开发社区搜索功能

image-20220620194738347

service增加:ElasticsearchService

@Service
public class ElasticsearchService {
   @Autowired
   private DiscussPostRepository discussRepository;
   @Autowired
   private ElasticsearchTemplate elasticTemplate;
   public void saveDiscussPost(DiscussPost post) {
       discussRepository.save(post);
  }
   public void deleteDiscussPost(int id) {
       discussRepository.deleteById(id);
  }
   public Page<DiscussPost> searchDiscussPost(String keyword, int current, int 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 elasticTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {
           @Override
           public <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());
          }
      });
  }
}

在DiscussPostController的addDiscussPost发帖方法和CommentController的addComment分别加上:

        // 触发发帖事件
       Event event = new Event()
              .setTopic(TOPIC_PUBLISH)
              .setUserId(user.getId())
              .setEntityType(ENTITY_TYPE_POST)
              .setEntityId(post.getId());
       eventProducer.fireEvent(event);
if (comment.getEntityType() == ENTITY_TYPE_POST) {
           // 触发发帖事件
           event = new Event()
                  .setTopic(TOPIC_PUBLISH)
                  .setUserId(comment.getUserId())
                  .setEntityType(ENTITY_TYPE_POST)
                  .setEntityId(discussPostId);
           eventProducer.fireEvent(event);

在EventConsumer中加上:

 // 消费发帖事件
   @KafkaListener(topics = {TOPIC_PUBLISH})
   public void handlePublishMessage(ConsumerRecord record) {
       if (record == null || record.value() == null) {
           logger.error("消息的内容为空!");
           return;
      }
       Event event = JSONObject.parseObject(record.value().toString(), Event.class);
       if (event == null) {
           logger.error("消息格式错误!");
           return;
      }
       DiscussPost post = discussPostService.findDiscussPostById(event.getEntityId());
       elasticsearchService.saveDiscussPost(post);//把查到的帖子存到es服务器里
  }

新建SearchController

@Controller
public class SearchController implements CommunityConstant {
   @Autowired
   private ElasticsearchService elasticsearchService;
   @Autowired
   private UserService userService;
   @Autowired
   private LikeService likeService;
   // search?keyword=xxx
   @RequestMapping(path = "/search", method = RequestMethod.GET)
   public String search(String keyword, Page page, Model model) {
       // 搜索帖子
       org.springframework.data.domain.Page<DiscussPost> searchResult =
               elasticsearchService.searchDiscussPost(keyword, page.getCurrent() - 1, page.getLimit());
       // 聚合数据
       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()));
               // 点赞数量
               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);
       page.setRows(searchResult == null ? 0 : (int) searchResult.getTotalElements());
       return "/site/search";
  }
}


标签:06,String,进展,private,toString,论坛,new,post,type
来源: https://www.cnblogs.com/zhangshuai2496689659/p/16394601.html