|
@@ -1,24 +1,12 @@
|
|
|
package com.tzld.longarticle.recommend.server.service.rank;
|
|
|
|
|
|
|
|
|
-import com.tzld.longarticle.recommend.server.model.Content;
|
|
|
-import com.tzld.longarticle.recommend.server.service.AccountContentPoolConfigService;
|
|
|
-import com.tzld.longarticle.recommend.server.service.score.ScoreParam;
|
|
|
-import com.tzld.longarticle.recommend.server.service.score.ScoreResult;
|
|
|
-import com.tzld.longarticle.recommend.server.service.score.ScoreService;
|
|
|
-import com.tzld.longarticle.recommend.server.service.score.strategy.SimilarityStrategy;
|
|
|
-import com.tzld.longarticle.recommend.server.service.score.strategy.ViewCountStrategy;
|
|
|
-import com.tzld.longarticle.recommend.server.util.CommonCollectionUtils;
|
|
|
-import com.tzld.longarticle.recommend.server.util.JSONUtils;
|
|
|
-import com.tzld.longarticle.recommend.server.util.TitleSimilarCheckUtil;
|
|
|
+import com.tzld.longarticle.recommend.server.service.ServiceBeanFactory;
|
|
|
+import com.tzld.longarticle.recommend.server.service.rank.strategy.DefaultRankStrategy;
|
|
|
+import com.tzld.longarticle.recommend.server.service.rank.strategy.RankV2Strategy;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
-import org.apache.commons.collections4.CollectionUtils;
|
|
|
-import org.apache.commons.lang3.RandomUtils;
|
|
|
-import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.stereotype.Service;
|
|
|
|
|
|
-import java.util.*;
|
|
|
-
|
|
|
/**
|
|
|
* @author dyp
|
|
|
*/
|
|
@@ -26,122 +14,19 @@ import java.util.*;
|
|
|
@Slf4j
|
|
|
public class RankService {
|
|
|
|
|
|
- @Autowired
|
|
|
- private ScoreService scoreService;
|
|
|
- @Autowired
|
|
|
- private AccountContentPoolConfigService accountContentPoolConfigService;
|
|
|
-
|
|
|
public RankResult rank(RankParam param) {
|
|
|
-
|
|
|
- log.info("RankParam {}", JSONUtils.toJson(param));
|
|
|
- ScoreResult scoreResult = scoreService.score(convertToScoreParam(param));
|
|
|
- log.info("ScoreResult {}", JSONUtils.toJson(scoreResult));
|
|
|
-
|
|
|
- Map<String, Map<String, Double>> scoreMap = scoreResult.getScoreMap();
|
|
|
-
|
|
|
- List<RankItem> items = CommonCollectionUtils.toList(param.getContents(), c -> {
|
|
|
- RankItem item = new RankItem();
|
|
|
- item.setContent(c);
|
|
|
- item.setScoreMap(scoreMap.get(c.getId()));
|
|
|
- return item;
|
|
|
-
|
|
|
- });
|
|
|
-
|
|
|
- // 1 排序
|
|
|
- String[] contentPools = accountContentPoolConfigService.getContentPools(param.getAccountName());
|
|
|
- Map<String, List<RankItem>> itemMap = new HashMap<>();
|
|
|
- for (RankItem c : items) {
|
|
|
- List<RankItem> data = itemMap.computeIfAbsent(c.getContent().getContentPoolType(), k -> new ArrayList<>());
|
|
|
- data.add(c);
|
|
|
- }
|
|
|
- List<RankItem> sortedItems = new ArrayList<>();
|
|
|
- for (int i = 0; i < contentPools.length; i++) {
|
|
|
- if (i == 1) {
|
|
|
- // 播放量排序
|
|
|
- List<RankItem> data = itemMap.get(contentPools[i]);
|
|
|
- if (CollectionUtils.isNotEmpty(data)) {
|
|
|
- Collections.sort(data, (o1, o2) -> -Double.compare(
|
|
|
- o1.getScore(ViewCountStrategy.class.getSimpleName()),
|
|
|
- o2.getScore(ViewCountStrategy.class.getSimpleName())));
|
|
|
- sortedItems.addAll(data);
|
|
|
- }
|
|
|
- } else {
|
|
|
- // 相似排序
|
|
|
- List<RankItem> data = itemMap.get(contentPools[i]);
|
|
|
- if (CollectionUtils.isNotEmpty(data)) {
|
|
|
- Collections.sort(data, (o1, o2) -> -Double.compare(
|
|
|
- o1.getScore(SimilarityStrategy.class.getSimpleName()),
|
|
|
- o2.getScore(SimilarityStrategy.class.getSimpleName())));
|
|
|
- sortedItems.addAll(data);
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- List<Content> contents = CommonCollectionUtils.toList(sortedItems, RankItem::getContent);
|
|
|
- log.info("Sort result {}", JSONUtils.toJson(contents));
|
|
|
-
|
|
|
- // 3 相似去重
|
|
|
- contents = deduplication(contents);
|
|
|
- log.info("Deduplication {}", JSONUtils.toJson(contents));
|
|
|
-
|
|
|
- // 4 文章按照内容池分组
|
|
|
- Map<String, List<Content>> contentMap = new HashMap<>();
|
|
|
- for (Content c : contents) {
|
|
|
- List<Content> data = contentMap.computeIfAbsent(c.getContentPoolType(), k -> new ArrayList<>());
|
|
|
- data.add(c);
|
|
|
- }
|
|
|
- log.info("ContentMap {}", JSONUtils.toJson(contentMap));
|
|
|
- // 5 按位置选文章
|
|
|
- List<Content> result = new ArrayList<>();
|
|
|
-
|
|
|
- // 头
|
|
|
- List<Content> pool = contentMap.get(contentPools[0]);
|
|
|
- if (CollectionUtils.isNotEmpty(pool)) {
|
|
|
- result.add(pool.get(RandomUtils.nextInt(0, Math.min(pool.size(), 5))));
|
|
|
- }
|
|
|
-
|
|
|
- // 次
|
|
|
- pool = contentMap.get(contentPools[1]);
|
|
|
- if (CollectionUtils.isNotEmpty(pool)) {
|
|
|
- result.add(pool.get(0));
|
|
|
- if (result.size() == 1 && pool.size() > 1) {
|
|
|
- result.add(pool.get(1));
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
- // 3-8
|
|
|
- pool = contentMap.get(contentPools[2]);
|
|
|
- if (CollectionUtils.isNotEmpty(pool)) {
|
|
|
- result.addAll(pool.subList(0, Math.min(pool.size(), param.getSize() - result.size())));
|
|
|
- }
|
|
|
-
|
|
|
- return new RankResult(result);
|
|
|
- }
|
|
|
-
|
|
|
- private ScoreParam convertToScoreParam(RankParam param) {
|
|
|
- ScoreParam scoreParam = new ScoreParam();
|
|
|
- scoreParam.setAccountName(param.getAccountName());
|
|
|
- scoreParam.setContents(param.getContents());
|
|
|
- return scoreParam;
|
|
|
+ RankStrategy strategy = getRankStrategy(param);
|
|
|
+ return strategy.rank(param);
|
|
|
}
|
|
|
|
|
|
- private List<Content> deduplication(List<Content> contents) {
|
|
|
- List<String> titles = new ArrayList<>();
|
|
|
- List<Content> result = new ArrayList<>();
|
|
|
- // 遍历所有列表
|
|
|
- for (Content c : contents) {
|
|
|
- if (similarity(c.getTitle(), titles)) {
|
|
|
- continue;
|
|
|
- } else {
|
|
|
- result.add(c);
|
|
|
- titles.add(c.getTitle());
|
|
|
- }
|
|
|
+ private RankStrategy getRankStrategy(RankParam param) {
|
|
|
+ switch (param.getStrategy()) {
|
|
|
+ case "ArticleRankV2":
|
|
|
+ return ServiceBeanFactory.getBean(RankV2Strategy.class);
|
|
|
+ default:
|
|
|
+ return ServiceBeanFactory.getBean(DefaultRankStrategy.class);
|
|
|
}
|
|
|
-
|
|
|
- return result;
|
|
|
}
|
|
|
|
|
|
- private boolean similarity(String title, List<String> titles) {
|
|
|
- return TitleSimilarCheckUtil.isDuplicateContent(title, titles);
|
|
|
- }
|
|
|
|
|
|
}
|