|
|
@@ -961,7 +961,77 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
exhausted[cur] = true;
|
|
|
}
|
|
|
}
|
|
|
- return paginateCandidates(param, merged);
|
|
|
+ Page<VideoContentItemVO> page = paginateCandidates(param, merged);
|
|
|
+ enrichWithDisplayData(page.getObjs(), param, user);
|
|
|
+ return page;
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 分页后按需补充分裂率和缺失封面,仅针对最终返回的 pageSize 条数据。
|
|
|
+ * 避免 fetchHotCandidates 拉取上万候选时全量查 content_platform_video_datastat_agg。
|
|
|
+ */
|
|
|
+ private void enrichWithDisplayData(List<VideoContentItemVO> items, VideoContentListParam param, ContentPlatformAccount user) {
|
|
|
+ if (CollectionUtils.isEmpty(items)) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ String type = getVideoContentListType(param.getType());
|
|
|
+ String datastatDt = planMapperExt.getVideoDatastatMaxDt();
|
|
|
+ String userChannel = user.getChannel();
|
|
|
+
|
|
|
+ // 1. 补缺失封面
|
|
|
+ List<Long> missingCoverIds = items.stream()
|
|
|
+ .filter(o -> !StringUtils.hasText(o.getCover()))
|
|
|
+ .map(VideoContentItemVO::getVideoId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (!missingCoverIds.isEmpty()) {
|
|
|
+ Map<Long, VideoDetail> coverMap = new HashMap<>();
|
|
|
+ for (List<Long> partition : Lists.partition(missingCoverIds, 20)) {
|
|
|
+ coverMap.putAll(messageAttachmentService.getVideoDetail(new HashSet<>(partition)));
|
|
|
+ }
|
|
|
+ for (VideoContentItemVO item : items) {
|
|
|
+ VideoDetail detail = coverMap.get(item.getVideoId());
|
|
|
+ if (detail != null) {
|
|
|
+ String cover = detail.getCover().substring(0, detail.getCover().indexOf("/watermark"));
|
|
|
+ item.setCover(cover);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 2. 补充分裂率
|
|
|
+ List<Long> videoIds = items.stream()
|
|
|
+ .map(VideoContentItemVO::getVideoId)
|
|
|
+ .filter(Objects::nonNull)
|
|
|
+ .distinct()
|
|
|
+ .collect(Collectors.toList());
|
|
|
+ if (videoIds.isEmpty()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ List<ContentPlatformVideoDataStatAgg> aggList = getTypeChannelVideoDataStatAggList(
|
|
|
+ datastatDt, type, Arrays.asList("sum", userChannel), videoIds);
|
|
|
+
|
|
|
+ Map<Long, Double> typeNormalMap = aggList.stream()
|
|
|
+ .filter(o -> "sum".equals(o.getChannel()) && "normal".equals(o.getStrategy()))
|
|
|
+ .collect(Collectors.toMap(ContentPlatformVideoDataStatAgg::getVideoId, ContentPlatformVideoDataStatAgg::getFissionRate));
|
|
|
+ Map<Long, Double> channelNormalMap = aggList.stream()
|
|
|
+ .filter(o -> userChannel.equals(o.getChannel()) && "normal".equals(o.getStrategy()))
|
|
|
+ .collect(Collectors.toMap(ContentPlatformVideoDataStatAgg::getVideoId, ContentPlatformVideoDataStatAgg::getFissionRate));
|
|
|
+ Map<Long, Double> channelRecommendMap = aggList.stream()
|
|
|
+ .filter(o -> userChannel.equals(o.getChannel()) && "recommend".equals(o.getStrategy()))
|
|
|
+ .collect(Collectors.toMap(ContentPlatformVideoDataStatAgg::getVideoId, ContentPlatformVideoDataStatAgg::getFissionRate));
|
|
|
+ Map<Long, Double> typeRecommendMap = aggList.stream()
|
|
|
+ .filter(o -> "sum".equals(o.getChannel()) && "recommend".equals(o.getStrategy()))
|
|
|
+ .collect(Collectors.toMap(ContentPlatformVideoDataStatAgg::getVideoId, ContentPlatformVideoDataStatAgg::getFissionRate));
|
|
|
+
|
|
|
+ for (VideoContentItemVO item : items) {
|
|
|
+ item.setIndustryFissionRate(typeNormalMap.get(item.getVideoId()));
|
|
|
+ item.setChannelFissionRate(channelNormalMap.get(item.getVideoId()));
|
|
|
+ item.setRecommendScore(channelRecommendMap.get(item.getVideoId()));
|
|
|
+ if (Objects.isNull(item.getRecommendScore())) {
|
|
|
+ item.setRecommendScore(typeRecommendMap.get(item.getVideoId()));
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
@@ -1265,8 +1335,29 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
|
|
|
String strategy = param.getSort() == 3 ? "recommend" : "normal";
|
|
|
List<ContentPlatformVideo> videoList = planMapperExt.getVideoList(param, dt, datastatDt, type, channel, strategy,
|
|
|
videoMinScore, 0, limit, sort);
|
|
|
- List<VideoContentItemVO> result = buildVideoContentItemVOList(videoList, type, "sum", user.getChannel(), datastatDt);
|
|
|
- return result == null ? new ArrayList<>() : result;
|
|
|
+ return toBasicVideoContentItems(videoList);
|
|
|
+ }
|
|
|
+
|
|
|
+ /**
|
|
|
+ * 轻量 PO→VO 转换,只设基础字段,不查 cover / fission_rate。
|
|
|
+ * cover 和 fission_rate 在分页后按需补充,避免对大量候选做无效 enrichment。
|
|
|
+ */
|
|
|
+ private List<VideoContentItemVO> toBasicVideoContentItems(List<ContentPlatformVideo> videoList) {
|
|
|
+ if (CollectionUtils.isEmpty(videoList)) {
|
|
|
+ return new ArrayList<>();
|
|
|
+ }
|
|
|
+ List<VideoContentItemVO> result = new ArrayList<>(videoList.size());
|
|
|
+ for (ContentPlatformVideo video : videoList) {
|
|
|
+ VideoContentItemVO item = new VideoContentItemVO();
|
|
|
+ item.setVideoId(video.getVideoId());
|
|
|
+ item.setTitle(video.getTitle());
|
|
|
+ item.setCover(video.getCover());
|
|
|
+ item.setVideo(video.getVideo());
|
|
|
+ item.setScore(video.getScore());
|
|
|
+ item.setExperimentId("hot");
|
|
|
+ result.add(item);
|
|
|
+ }
|
|
|
+ return result;
|
|
|
}
|
|
|
|
|
|
/**
|