RecommendService.java 6.11 KB
Newer Older
1 2 3 4 5 6
package com.tanpu.community.service;

import com.tanpu.common.util.JsonUtil;
import com.tanpu.community.api.beans.qo.ThemeAnalysDO;
import com.tanpu.community.api.beans.resp.PythonResponse;
import com.tanpu.community.dao.entity.community.ThemeEntity;
7
import com.tanpu.community.util.BizUtils;
8 9
import com.tanpu.community.util.ConvertUtil;
import lombok.extern.slf4j.Slf4j;
10
import org.apache.commons.collections4.ListUtils;
11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.*;
import java.util.stream.Collectors;

@Slf4j
@Service
public class RecommendService {

    @Value("${recommend.python.enable}")
    public String enablePython;


    @Value("${recommend.python.url}")
    public String pythonUrl;
    @Value("${recommend.ratio.hot}")
    public Integer hotRatio;
    @Value("${recommend.ratio.new}")
    public Integer newRatio;
    @Value("${recommend.ratio.python}")
    public Integer pythonRatio;


    @Autowired
    private RankService rankService;

    @Autowired
    private ThemeService themeService;

44 45 46
    @Autowired
    private VisitSummaryService visitSummaryService;

张辰's avatar
张辰 committed
47
    // 最新
48
    private List<ThemeAnalysDO> recentThemeList = new ArrayList<>();
张辰's avatar
张辰 committed
49
    // 推荐
50 51
    private Map<String, List<String>> recommondList = new HashMap<>();

52
    public List<String> getRecommendThemes(Integer pageStart, Integer pageSize, String userId) {
53
        //最热话题,剔除当前用户的主题
54
        // todo pageNo , pageSize
张辰's avatar
张辰 committed
55
        List<String> hotThemeIds = rankService.getHotestThemes().stream()
56 57 58 59
                .map(ThemeAnalysDO::getThemeId)
                .collect(Collectors.toList());

        //最新话题,剔除当前用户的主题
60
        List<String> newThemeIds = getNewestThemes().stream()
61 62 63 64 65 66
                .map(ThemeAnalysDO::getThemeId)
                .collect(Collectors.toList());

        //推荐话题
        List<String> recThemeIds = getPythonRecommendList(userId);

67
        List<String> result = mergeRecommend(hotThemeIds, newThemeIds, recThemeIds);
68 69
        result = result.stream().limit(pageSize).collect(Collectors.toList());
        return result;
70 71
    }

72 73
    // 获取最新话题
    public List<ThemeAnalysDO> getNewestThemes() {
74 75 76 77 78 79
        if (recentThemeList.size() == 0) {
            refreshNewestThemes();
        }
        return recentThemeList;
    }

80
    // 从数据库查询最新主题
81 82 83 84 85 86 87 88 89 90 91 92 93 94
    public void refreshNewestThemes() {
        List<ThemeEntity> themeEntities = themeService.queryLatestThemes(100);
        this.recentThemeList = ConvertUtil.themeEntityToAnalysDOs(themeEntities);
    }

    //查询python计算推荐列表
    public List<String> getPythonRecommendList(String userId) {
        if (recommondList.containsKey(userId)) {
            return recommondList.get(userId);
        } else {
            return refreshPythonRecommendList(userId);
        }
    }

95
    //HTTP查询python推荐主题 python返回最多50个
96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
    public List<String> refreshPythonRecommendList(String userId) {
        if (!"true".equals(enablePython)) {
            return Collections.emptyList();
        }
        RestTemplate restTemplate = new RestTemplate();
        HashMap<String, String> param = new HashMap<>();
        param.put("user_id", userId);
        try {
            String response = restTemplate.getForObject(pythonUrl, String.class, param);
            PythonResponse pythonResponse = JsonUtil.toBean(response, PythonResponse.class);
            recommondList.put(userId, pythonResponse.getAttributes());
            return pythonResponse.getAttributes();
        } catch (Exception e) {
            log.error("调用python失败");
            return Collections.emptyList();
        }


    }

刘基明's avatar
刘基明 committed
116 117
    // 合并,去重
    private List<String> mergeList(List<String> hotThemeIds, List<String> newThemeIds, List<String> recThemeIds, Set<String> set) {
刘基明's avatar
刘基明 committed
118
        ArrayList<String> result = new ArrayList<>();
刘基明's avatar
刘基明 committed
119
        // 3个集合的指针
刘基明's avatar
刘基明 committed
120 121 122 123 124 125 126 127 128 129
        Integer hotIdx = 0;
        Integer newIdx = 0;
        Integer recIdx = 0;
        while (hotThemeIds.size() > hotIdx || newThemeIds.size() > newIdx || recThemeIds.size() > recIdx) {
            int hotTimes = hotRatio;
            int newTimes = newRatio;
            int recTimes = pythonRatio;
            String id;
            while (hotTimes > 0 && hotThemeIds.size() > hotIdx) {
                id = hotThemeIds.get(hotIdx);
刘基明's avatar
刘基明 committed
130 131 132 133 134
                if (!set.contains(id)){
                    result.add(id);
                    set.add(id);
                }

刘基明's avatar
刘基明 committed
135 136 137 138 139
                hotIdx++;
                hotTimes--;
            }
            while (newTimes > 0 && newThemeIds.size() > newIdx) {
                id = newThemeIds.get(newIdx);
刘基明's avatar
刘基明 committed
140 141 142 143 144
                if (!set.contains(id)){
                    result.add(id);
                    set.add(id);
                }

刘基明's avatar
刘基明 committed
145 146 147 148 149
                newIdx++;
                newTimes--;
            }
            while (recTimes > 0 && recThemeIds.size() > recIdx) {
                id = recThemeIds.get(recIdx);
刘基明's avatar
刘基明 committed
150 151 152 153 154
                if (!set.contains(id)){
                    result.add(id);
                    set.add(id);
                }

刘基明's avatar
刘基明 committed
155 156 157 158 159 160 161 162
                recIdx++;
                recTimes--;
            }

        }
        return result;
    }

163 164 165 166 167 168 169 170 171 172 173
    // 按照 6,3,1的比例
    private List<String> mergeRecommend(List<String> hotIds, List<String> newestIds, List<String> recmdIds) {
        List<String> retList = new ArrayList<>();

        int round = 0;
        while (true) {
            int hotStart = round * 6;
            int newestStart = round * 3;
            int recmdStart = round;
            if (hotStart >= hotIds.size() && newestStart >= newestIds.size() && recmdStart >= recmdIds.size()) {
                break;
174
            }
175 176 177
            retList.addAll(BizUtils.subList(hotIds, hotStart, hotStart + 6));
            retList.addAll(BizUtils.subList(newestIds, newestStart, newestStart + 3));
            retList.addAll(BizUtils.subList(recmdIds, recmdStart, recmdStart + 1));
178

179
            round++;
180
        }
181
       return retList;
182 183 184 185
    }


}