- 将帖子保存至Elasticsearch服务器。
- 从Elasticsearch服务器删除帖子。
- 从Elasticsearch服务器搜索帖子。
- 发布帖子时,将帖子异步的提交到Elasticsearch服务器。
- 增加评论时,将帖子异步的提交到Elasticsearch服务器。
- 在消费组件中增加一个方法,消费帖子发布事件。
- 在控制器中处理搜索请求,在HTML上显示搜索结果
@Controller
public class SearchController implements CommunityConstant {
@Autowired
private ElasticsearchService elasticsearchService;
@Autowired
private UserService userService;
@Autowired
private LikeService likeService;
@RequestMapping(value = "/search",method = RequestMethod.GET)
public String search(String keyword, Page page, Model model){
//搜索帖子
org.springframework.data.domain.Page searchResult =
elasticsearchService.searchDiscussPost(keyword, page.getCurrent() - 1, page.getLimit());
//聚合数据:帖子,帖子作者,点赞数,回复数
List
@Service
public class ElasticsearchService {
@Autowired
private ElasticsearchTemplate elasticsearchTemplate;
@Autowired
private DiscussPostRepository discussPostRepository;
//当新发布(修改)一条帖子时,要将帖子数据传入到elasticsearch中
public void saveDiscussPost(DiscussPost discussPost){
discussPostRepository.save(discussPost);
}
//当删除一条帖子时,需要将elasticsearch中内容同步删除
public void deleteDiscussPost(int id){
discussPostRepository.deleteById(id);
}
//实现搜索业务
public Page searchDiscussPost(String keyword,int current,int limit){
SearchQuery searchQuery=new NativeSearchQueryBuilder() //构造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)) //构造分页条件:PageRequest.of(0,10):当前页(从0开始 ,每页显示10条
.withHighlightFields(
//是否高亮显示:对搜索的关键词加标签
new HighlightBuilder.Field("title").preTags("").postTags(""),
new HighlightBuilder.Field("content").preTags("").postTags("")
).build(); //返回SearchQuery接口实现类
return elasticsearchTemplate.queryForPage(searchQuery, DiscussPost.class, new SearchResultMapper() {
@Override
public AggregatedPage mapResults(SearchResponse searchResponse, Class aClass, Pageable pageable) {
//处理
SearchHits hits = searchResponse.getHits(); //获取搜索的结果数据
if(hits.totalHits<0){
return null; //未获取到结果直接返回
}
//将获取到的结果装进list中
List list = new ArrayList<>();
//遍历命中数据
for(SearchHit hit:hits){
//将命中数据吧包装到实体类中
DiscussPost post=new DiscussPost();
//数据形式是以json形式存在的,并将json数据封装为了map格式
//因此将数据以map形式取出--->转为string再存入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();//原始的title
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.totalHits
,searchResponse.getAggregations(),searchResponse.getScrollId(),hits.getMaxScore());
}
});
}
}
@Repository
public interface DiscussPostRepository extends ElasticsearchRepository {
}
发送帖子后,需要将帖子同步到elasticsearch中
@RequestMapping(value = "/add",method = RequestMethod.POST)
@ResponseBody
public 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);
//发布帖子后,同步到elasticsearch中
//利用事件进行发送
Event event=new Event()
.setTopic(TOPIC_PUBLISH)
.setUserId(user.getId())
.setEntityType(ENTITY_TYPE_POST)
.setEntityId(post.getId());
eventProducer.fireEvent(event);
return CommunityUtil.getJsonString(0,"发布成功!");
}
添加评论后,需要更新elasticsearch中数据
@RequestMapping(value = "/add/{discussPostId}",method = RequestMethod.POST)
public String addComment(@PathVariable("discussPostId") int discussPostId, Comment comment){
comment.setStatus(0);
comment.setCreateTime(new Date());
comment.setUserId(hostHolder.getUser().getId());
commentService.addComment(comment);
//发送评论后发送通知通知对方
Event event=new Event()
.setTopic(TOPIC_COMMENT)
.setUserId(hostHolder.getUser().getId())
.setEntityType(comment.getEntityType())
.setEntityId(comment.getEntityId())
.setData("postId",discussPostId); //最终发送的消息还有点击查看,要链接到帖子详情页面,需要知道帖子id
//帖子的作者:评论的是帖子帖子--》帖子表; 评论的是评论---》评论表
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){
event=new Event()
.setTopic(TOPIC_PUBLISH)
.setUserId(comment.getUserId())
.setEntityType(ENTITY_TYPE_POST)
.setEntityId(discussPostId);
eventProducer.fireEvent(event);
}
return "redirect:/discuss/detail/" + discussPostId;
}
//消费者消费发帖事件--->同步到elasticsearch中
@KafkaListener(topics = TOPIC_PUBLISH)
public void handleDiscussPost(ConsumerRecord record){
//先进行判断record是否为空:未发事件或者发送的事件为空
if(record==null|| record.value()==null){
logger.error("发送的消息为空!");
return;
}
//事件不为空:将事件转换为Event对象
Event event= JSONObject.parseObject(record.value().toString(),Event.class);
//判断对象是否为空
if(event==null){
logger.error("消息格式错误!");
return;
}
//从事件中获取帖子id
DiscussPost post = discussPostService.findDiscussPostById(event.getEntityId());
//将查询到的帖子同步到elasticsearch中
elasticsearchService.saveDiscussPost(post);
}
#配置ElasticsearchProperties spring.data.elasticsearch.cluster-name=(自己的cluster-name) spring.data.elasticsearch.cluster-nodes=自己的服务器ip:9300 spring.elasticsearch.rest.uris=自己的服务器ip:9200 spring.elasticsearch.rest.username=运行elasticsearch的用户 spring.elasticsearch.rest.password=用户密码 spring.data.elasticsearch.repositories.enabled=true #192.168.10.100:9200 (http端口 #192.168.10.100:9300 (tcp端口
-
备战春招,面试刷题跟他复习,一个月全搞定!
金三银四的金三已经到了,你还沉浸在过年的喜悦中吗? 如果是,那我要让你清醒一下了:目前大部分公司已经开启了内推,正式网申也将在3月份陆续开始,金三银四,春招的求职黄金时期已经来啦!!! 再不准备,作为19应届生的你可能就找不到工作了。。。作为20届实习生的你可能就找不到实习了。。。 现阶段时间紧,任务重,能做到短时间内快速提升的也就只有算法了, 那么算法要怎么复习?重点在哪里?常见笔试面试算法题型和解题思路以及最优代码是怎样的? 跟左程云老师学算法,不仅能解决以上所有问题,还能在短时间内得到最大程度的提升!!!
寒江雪
发布于 2019-04-15 15:32:18
- 赞 11
- |
- 回复 7