Commit e4929e95 authored by 吴泽佳's avatar 吴泽佳
parents 8e175fe6 16b5ae0a
......@@ -23,7 +23,6 @@ public class ThemeQo implements Serializable {
@ApiModelProperty(value = "主题ID")
public String themeId;
@ApiModelProperty(value = "被转发的主题")
public String formerThemeId;
......@@ -116,4 +115,8 @@ public class ThemeQo implements Serializable {
@ApiModelProperty("工作室简介")
private String workshopIntroduction;//工作室简介
// 搜索页用
// 使用关键词搜索时,在列表页展示的简要内容,内容带关键字.
public String briefContent4FullSearch;
}
......@@ -23,11 +23,18 @@ public class TopicRankQo {
@ApiModelProperty(value = "讨论量")
private Integer disscussCount;
@ApiModelProperty(value = "是否置顶")
private Integer isTop;
/**
* TODO 热度计算算法
* @return
*/
public Integer getRank(){
//顶置话题
if (isTop>0){
return Integer.MAX_VALUE;
}
return this.viewCount+this.disscussCount*3;
}
}
......@@ -2,8 +2,10 @@ package com.tanpu.community.api.beans.resp;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
......@@ -14,6 +16,8 @@ import java.math.BigDecimal;
**/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
@ApiModel(description = "客户信息")
public class Customer {
......
......@@ -9,6 +9,8 @@ import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.apache.ibatis.annotations.Update;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.List;
/**
......@@ -31,4 +33,7 @@ public interface VisitSummaryMapper extends BaseMapper<VisitSummaryEntity> {
@Select("select ref_id as id, count(1) as times from visit_summary ${ew.customSqlSegment}")
List<TimesCountEntity> selectCountByThemeIds(@Param(Constants.WRAPPER)LambdaQueryWrapper wrapper);
@Select("select ref_id from visit_summary where visitor_id=#{visitorId} and date(create_time) between #{startDate} and #{endDate}")
List<String> selectRefIdByUserIdAndCreateBetween(@Param("visitorId") String visitorId, @Param("startDate") Date startDate, @Param("endDate") Date endDate);
}
......@@ -69,7 +69,7 @@ public class CommentManager {
List<CommentEntity> commentEntities = commentService.selectByThemeId(themeId);
List<CommentQo> commentQos = ConvertUtil.commentEntity2Qos(commentEntities);
Set<String> likeCommentList = collectionService.getListByUser(userId, CollectionTypeEnum.LIKE_COMMENT);
Set<String> likeCommentList = collectionService.getSetByUser(userId, CollectionTypeEnum.LIKE_COMMENT);
for (CommentQo commentQo : commentQos) {
//查询用户信息
......
......@@ -26,6 +26,7 @@ import com.tanpu.community.util.RankUtils;
import com.tanpu.community.util.TencentcloudUtils;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.BeanUtils;
......@@ -93,7 +94,6 @@ public class ThemeManager {
ThemeFullSearchResp resp = new ThemeFullSearchResp();
// 按时间倒叙查询
// todo redis
List<ESThemeQo> esIds = esService.queryThemeIdByContentAndTitle(keyword, from, pageSize * 5);
if (esIds.isEmpty()) {
return resp;
......@@ -104,7 +104,14 @@ public class ThemeManager {
return !excludeIds.contains(tId);
}).limit(pageSize).collect(Collectors.toList());
List<ThemeQo> themes = ConvertUtil.themeEntitiesToDTOs(themeService.queryByThemeIds(filterEsIds));
resp.themes = convertEntityToQo(themeService.queryByThemeIds(filterEsIds), userId);
// 截取关键词出现的那一部分段落
for (ThemeQo theme : resp.themes) {
theme.briefContent4FullSearch = BizUtils.getThemeContent(keyword, theme);
}
resp.excludeIds.addAll(filterEsIds);
return resp;
......@@ -123,8 +130,13 @@ public class ThemeManager {
themeEntity.setAuthorId(userId);
themeEntity.setContent(JsonUtil.toJson(req.getContent()));
//讨论类型,将讨论中的文本放入到discussContent中
if (ThemeTypeEnum.DISCUSSION.getCode().equals(themeEntity.getThemeType()))
themeEntity.setDiscussContent(req.getContent().get(0).getValue());
if (ThemeTypeEnum.DISCUSSION.getCode().equals(themeEntity.getThemeType())) {
String content = req.getContent().get(0).getValue();
if (content.length()>256){
content= content.substring(0,255);
}
themeEntity.setDiscussContent(content);
}
//腾讯云敏感词校验
checkContent(themeEntity.getContent());
......@@ -187,51 +199,50 @@ public class ThemeManager {
public ThemeListResp queryThemes(ThemeListReq req, String userId) {
Integer pageStart = (req.page.pageNumber - 1) * req.page.pageSize;
Integer pageSize = req.page.pageSize;
Integer querySize = pageSize * 2;
Integer querySize = pageSize * 3;
List<ThemeEntity> themes = new ArrayList<>();
if (ThemeListTypeEnum.RECOMMEND.getCode().equals(req.getType())) {
//推荐
List<String> recmdIds = recommendService.getRecommendThemes(pageStart, querySize, userId);
//去重已看过(查看正文)
recmdIds = visitSummaryService.filterUserNotVisited(userId, recmdIds);
// 需要筛掉用户访问过详情的 & 最近出现在列表页过的.
List<String> visitedIds = visitSummaryService.queryUserRecentVisited(userId);
List<String> excludes = ListUtils.union(req.excludeIds, visitedIds);
List<String> recmdIds = recommendService.getRecommendThemes(pageStart, querySize, userId, excludes);
recmdIds = BizUtils.subList(recmdIds, pageStart, pageSize);
themes = themeService.queryByThemeIds(recmdIds);
themes = RankUtils.sortThemeEntityByIds(themes, recmdIds);
// filter用户自己的
themes = themes.stream().filter(t -> {
return !userId.equals(t.getAuthorId()) && !req.excludeIds.contains(t.getThemeId());
}).collect(Collectors.toList());
// todo pageNo pageSize
themes = BizUtils.subList(themes, 0, req.page.pageSize);
} else if (ThemeListTypeEnum.FOLLOW.getCode().equals(req.getType())) {
//TODO 临时埋点,接入新埋点后删除
// TODO 临时埋点,接入新埋点后删除
if (CollectionUtils.isEmpty(req.getExcludeIds())) {
visitSummaryService.addPageView(userId, userId, VisitTypeEnum.FOLLOW_THEME_VIEW);
}
//根据关注列表查询
// 根据关注列表查询,按时间倒序
List<String> fansList = followRelService.queryFansByFollowerId(userId);
themes = themeService.queryByUserIds(fansList, pageStart, pageSize);
themes = themeService.queryByUserIdsCreateDesc(fansList, pageStart, pageSize);
} else if (ThemeListTypeEnum.TOPIC_HOT.getCode().equals(req.getType())) {
//根据话题查询热门
// 根据话题查询热门
if (StringUtils.isEmpty(req.getTopicId())) {
throw new BizException("TopicId为空");
}
List<String> rankThemeIds = rankService.getRankThemeListByTopic(req.getTopicId(),pageSize,req.excludeIds);
List<String> rankThemeIds = rankService.getRankThemeListByTopic(req.getTopicId(), req.excludeIds);
rankThemeIds = BizUtils.subList(rankThemeIds, pageStart, pageSize);
themes = themeService.queryByThemeIds(rankThemeIds);
themes = RankUtils.sortThemeEntityByIds(themes, rankThemeIds);
} else if (ThemeListTypeEnum.TOPIC_LATEST.getCode().equals(req.getType())) {
//根据话题查询最新
if (StringUtils.isEmpty(req.getTopicId())) {
throw new BizException("TopicId为空");
}
themes = themeService.queryNewestByTopic(req.topicId, pageStart, pageSize);
themes = themeService.queryNewestByTopic(req.topicId, pageStart, querySize, req.excludeIds);
}
ThemeListResp resp = new ThemeListResp();
resp.excludeIds = req.excludeIds;
resp.excludeIds.addAll(themes.stream().map(ThemeEntity::getThemeId).collect(Collectors.toList()));
......@@ -302,12 +313,15 @@ public class ThemeManager {
List<ThemeQo> commentThemeList = getCommentThemeQos(req, userId);
return commentThemeList;
case 3://点赞
Set<String> likeThemeIds = collectionService.getListByUser(req.getUserId(), CollectionTypeEnum.LIKE_THEME);
themeEntities = themeService.queryByThemeIds(new ArrayList<>(likeThemeIds), req.getLastId(), req.getPageSize());
List<String> likeThemeIds = collectionService.getListByUser(req.getUserId(), CollectionTypeEnum.LIKE_THEME);
themeEntities = themeService.queryByThemeIds(likeThemeIds, req.getLastId(), req.getPageSize());
themeEntities = RankUtils.sortThemeEntityByIds(themeEntities, likeThemeIds);
break;
case 4://收藏
Set<String> collectThemeIds = collectionService.getListByUser(req.getUserId(), CollectionTypeEnum.COLLECT_THEME);
themeEntities = themeService.queryByThemeIds(new ArrayList<>(collectThemeIds), req.getLastId(), req.getPageSize());
List<String> collectThemeIds = collectionService.getListByUser(req.getUserId(), CollectionTypeEnum.COLLECT_THEME);
themeEntities = themeService.queryByThemeIds(collectThemeIds, req.getLastId(), req.getPageSize());
themeEntities = RankUtils.sortThemeEntityByIds(themeEntities, collectThemeIds);
break;
}
List<ThemeQo> themeQos = convertEntityToQo(themeEntities, userId);
......
......@@ -66,7 +66,7 @@ public class CollectionService {
}
// 根据用户id和行为type获取target_id列表
public Set<String> getListByUser(String userId, CollectionTypeEnum type) {
public Set<String> getSetByUser(String userId, CollectionTypeEnum type) {
return collectionMapper.selectList(new LambdaQueryWrapper<CollectionEntity>()
.eq(CollectionEntity::getUserId, userId)
.eq(CollectionEntity::getCollectionType, type.getCode())
......@@ -74,6 +74,15 @@ public class CollectionService {
.stream().map(CollectionEntity::getTargetId).collect(Collectors.toSet());
}
// 根据用户id和行为type获取target_id列表
public List<String> getListByUser(String userId, CollectionTypeEnum type) {
return collectionMapper.selectList(new LambdaQueryWrapper<CollectionEntity>()
.eq(CollectionEntity::getUserId, userId)
.eq(CollectionEntity::getCollectionType, type.getCode())
.eq(CollectionEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode()))
.stream().map(CollectionEntity::getTargetId).collect(Collectors.toList());
}
// 统计单个对象(主题、评论)的数量(点赞、收藏)
public Integer getCountByTypeAndId(String targetId, CollectionTypeEnum type) {
......
......@@ -113,7 +113,7 @@ public class RankService {
for (TopicRankQo topic : topicRankQos) {
List<String> themeIds = themeService.queryThemeIdsByTopic(topic.getTopicId());
if (CollectionUtils.isEmpty(themeIds)) {
topic.setViewCount(0);
topic.setViewCount(countMapByTargetIds.getOrDefault(topic.getTopicId(),0));
topic.setDisscussCount(0);
continue;
}
......@@ -138,25 +138,7 @@ public class RankService {
}
/**
* 最新和热门主题集合
*
* @param hotCount
* @param newCount
* @return
*/
// public List<String> getHotAndNewThemes(Integer hotCount, Integer newCount, String userId) {
// Set<String> hotThemeIds = this.hotestThemes.stream().limit(hotCount)
// .filter(o -> !userId.equals(o.getAuthorId()))
// .map(ThemeAnalysDO::getThemeId)
// .collect(Collectors.toSet());
// Set<String> newThemeIds = themeService.selectExcludeUser(null, null, newCount)
// .stream().map(ThemeEntity::getThemeId).collect(Collectors.toSet());
// hotThemeIds.addAll(newThemeIds);
// return new ArrayList<>(hotThemeIds);
// }
/**
* 话题详情
* 从排序列表中返回话题详情
*
* @param topicId 话题Id
* @return
......@@ -197,13 +179,13 @@ public class RankService {
return hotestThemes;
}
public List<String> getRankThemeListByTopic(String topicId, Integer pageSize, List<String> excludeIds) {
public List<String> getRankThemeListByTopic(String topicId, List<String> excludeIds) {
if (this.hotestThemes.size() == 0) {
this.rankThemes();
}
HashSet<String> excludSet = new HashSet<>(excludeIds);
return hotestThemes.stream().filter(o -> topicId.equals(o.getTopicId()) && !excludSet.contains(o.getThemeId()))
.limit(pageSize)
return hotestThemes.stream()
.filter(o -> topicId.equals(o.getTopicId()) && !excludeIds.contains(o.getThemeId()))
.map(ThemeAnalysDO::getThemeId)
.collect(Collectors.toList());
}
......
......@@ -49,24 +49,32 @@ public class RecommendService {
// 推荐
private Map<String, List<String>> recommondList = new HashMap<>();
public List<String> getRecommendThemes(Integer pageStart, Integer pageSize, String userId) {
//最热话题,剔除当前用户的主题
// todo pageNo , pageSize
public List<String> getRecommendThemes(Integer pageStart, Integer pageSize, String userId, List<String> excludeIds) {
// 最热话题,筛掉用户发表的 & 最近看过的 & excludeIds
List<String> hotThemeIds = rankService.getHotestThemes().stream()
.map(ThemeAnalysDO::getThemeId)
.collect(Collectors.toList());
.filter(theme -> {
return !excludeIds.contains(theme.getThemeId()) && !userId.equals(theme.getAuthorId());
})
.map(ThemeAnalysDO::getThemeId).collect(Collectors.toList());
hotThemeIds = BizUtils.subList(hotThemeIds, pageStart, pageSize);
//最新话题,剔除当前用户的主题
//最新话题,筛掉用户发表的 & 最近看过的 & excludeIds
List<String> newThemeIds = getNewestThemes().stream()
.map(ThemeAnalysDO::getThemeId)
.collect(Collectors.toList());
.filter(theme -> {
return !excludeIds.contains(theme.getThemeId()) && !userId.equals(theme.getAuthorId());
})
.map(ThemeAnalysDO::getThemeId).collect(Collectors.toList());
newThemeIds = BizUtils.subList(newThemeIds, pageStart, pageSize);
//推荐话题
List<String> recThemeIds = getPythonRecommendList(userId);
List<String> result = mergeRecommend(hotThemeIds, newThemeIds, recThemeIds);
result = result.stream().limit(pageSize).collect(Collectors.toList());
return result;
List<String> recThemeIds = getPythonRecommendList(userId).stream()
.filter(id -> {
return !excludeIds.contains(id);
}).collect(Collectors.toList());
recThemeIds = BizUtils.subList(recThemeIds, pageStart, pageSize);
// merge
return mergeRecommend(hotThemeIds, newThemeIds, recThemeIds);
}
// 获取最新话题
......
......@@ -206,10 +206,13 @@ public class ThemeService {
* @param pageSize 查询数量
* @return
*/
public List<ThemeEntity> queryNewestByTopic(String topidId, Integer pageNo, Integer pageSize) {
public List<ThemeEntity> queryNewestByTopic(String topidId, Integer pageNo, Integer pageSize, List<String> excludeIds) {
LambdaQueryWrapper<ThemeEntity> queryWrapper = new LambdaQueryWrapper<ThemeEntity>()
.eq(ThemeEntity::getTopicId, topidId)
.last("limit " + pageNo + ", " + pageSize)
.eq(ThemeEntity::getTopicId, topidId);
if (!excludeIds.isEmpty()) {
queryWrapper.notIn(ThemeEntity::getThemeId, excludeIds);
}
queryWrapper.last("limit " + pageNo + ", " + pageSize)
.orderByDesc(ThemeEntity::getCreateTime)
.eq(ThemeEntity::getDeleteTag, DeleteTagEnum.NOT_DELETED.getCode());
return themeMapper.selectList(queryWrapper);
......@@ -233,7 +236,7 @@ public class ThemeService {
* @param pageSize
* @return
*/
public List<ThemeEntity> queryByUserIds(List<String> userIds, Integer pageStart, Integer pageSize) {
public List<ThemeEntity> queryByUserIdsCreateDesc(List<String> userIds, Integer pageStart, Integer pageSize) {
if (CollectionUtils.isEmpty(userIds)){
return Collections.emptyList();
}
......
......@@ -9,11 +9,13 @@ import com.tanpu.community.dao.mapper.community.VisitSummaryMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.ListUtils;
import org.apache.commons.lang3.time.DateUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
......@@ -26,6 +28,14 @@ public class VisitSummaryService {
@Resource
private VisitSummaryMapper visitSummaryMapper;
// 获取用户7天内访问过的
public List<String> queryUserRecentVisited(String userId) {
Date endDate = new Date();
Date startDate = DateUtils.addDays(endDate, -7);
List<String> visited = visitSummaryMapper.selectRefIdByUserIdAndCreateBetween(userId, startDate, endDate);
return visited;
}
// 从refIds中去掉用户已经访问过的
public List<String> filterUserNotVisited(String userId, List<String> refIds) {
if (refIds.isEmpty()) {
......@@ -38,7 +48,6 @@ public class VisitSummaryService {
return ListUtils.subtract(refIds, visited);
}
public List<String> queryUserVisited(String userId) {
List<String> visited = visitSummaryMapper.selectList(new LambdaQueryWrapper<VisitSummaryEntity>()
.eq(VisitSummaryEntity::getVisitorId, userId))
.stream().map(VisitSummaryEntity::getRefId).distinct().collect(Collectors.toList());
......@@ -102,7 +111,7 @@ public class VisitSummaryService {
}
}
//统计主题集合的浏览量
//统计行为集合的浏览量
public Map<String, Integer> getCountMapByTargetIds(List<String> refIds, VisitTypeEnum type) {
if (CollectionUtils.isEmpty(refIds)){
return new HashMap<>();
......
......@@ -9,6 +9,7 @@ import com.tanpu.community.dao.entity.community.ThemeEntity;
import com.tanpu.community.model.ESWrapper;
import lombok.extern.slf4j.Slf4j;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.MatchPhraseQueryBuilder;
import org.elasticsearch.index.query.MatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.search.SearchHit;
......@@ -44,8 +45,8 @@ public class ESService {
SearchSourceBuilder search = new SearchSourceBuilder();
BoolQueryBuilder boolQb = QueryBuilders.boolQuery();
MatchQueryBuilder contentQb = QueryBuilders.matchQuery("textContent", keyword);
MatchQueryBuilder titleQb = QueryBuilders.matchQuery("title", keyword);
MatchPhraseQueryBuilder contentQb = QueryBuilders.matchPhraseQuery("textContent", keyword);
MatchPhraseQueryBuilder titleQb = QueryBuilders.matchPhraseQuery("title", keyword);
boolQb.should(contentQb);
boolQb.should(titleQb);
......
package com.tanpu.community.util;
import com.alibaba.fastjson.JSON;
import com.tanpu.community.api.beans.qo.ThemeContentQo;
import com.tanpu.community.api.beans.qo.ThemeQo;
import com.tanpu.community.api.enums.RelTypeEnum;
import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
......@@ -15,4 +18,23 @@ public class BizUtils {
int realEnd = Math.min(start + size, list.size());
return list.subList(start, realEnd);
}
public static String getThemeContent(String keyword, ThemeQo theme) {
for (ThemeContentQo paragraph : theme.content) {
if (paragraph.getType().equals(RelTypeEnum.TEXT.type)) {
int idx = paragraph.getValue().indexOf(keyword);
if (idx == -1) {
continue;
} else if (idx < 30) {
// 如果关键词在段落偏头部的部分,则全部返回给前端,前端自由展示
return paragraph.getValue();
} else {
// 否则,保留关键词 向前20个字符
return paragraph.getValue().substring(idx - 20);
}
}
}
return "";
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment