|
@@ -0,0 +1,106 @@
|
|
|
+package com.tzld.piaoquan.recommend.server.implement.recall;
|
|
|
+
|
|
|
+
|
|
|
+import com.tzld.piaoquan.recommend.server.common.ThreadPoolFactory;
|
|
|
+import com.tzld.piaoquan.recommend.server.framework.candidiate.Candidate;
|
|
|
+import com.tzld.piaoquan.recommend.server.framework.common.User;
|
|
|
+import com.tzld.piaoquan.recommend.server.framework.recaller.AbstractFilter;
|
|
|
+import com.tzld.piaoquan.recommend.server.framework.recaller.FilterConfigInfo;
|
|
|
+import com.tzld.piaoquan.recommend.server.gen.recommend.RecommendRequest;
|
|
|
+import com.tzld.piaoquan.recommend.server.model.Video;
|
|
|
+import com.tzld.piaoquan.recommend.server.service.filter.strategy.VideoView;
|
|
|
+import org.apache.commons.collections4.CollectionUtils;
|
|
|
+import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
+import org.springframework.beans.factory.annotation.Qualifier;
|
|
|
+import org.springframework.dao.DataAccessException;
|
|
|
+import org.springframework.data.mongodb.core.MongoTemplate;
|
|
|
+import org.springframework.data.mongodb.core.query.Criteria;
|
|
|
+import org.springframework.data.mongodb.core.query.Query;
|
|
|
+import org.springframework.data.redis.core.RedisOperations;
|
|
|
+import org.springframework.data.redis.core.RedisTemplate;
|
|
|
+import org.springframework.data.redis.core.SessionCallback;
|
|
|
+import org.springframework.data.redis.core.SetOperations;
|
|
|
+
|
|
|
+import java.util.HashSet;
|
|
|
+import java.util.List;
|
|
|
+import java.util.Set;
|
|
|
+import java.util.concurrent.TimeUnit;
|
|
|
+
|
|
|
+public class ViewedHistoryFilter extends AbstractFilter<Video> {
|
|
|
+
|
|
|
+
|
|
|
+ protected Set<String> historySet;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ @Qualifier("longVideoRedisTemplate")
|
|
|
+ private RedisTemplate<String, String> redisTemplate;
|
|
|
+
|
|
|
+ @Autowired
|
|
|
+ private MongoTemplate mongoTemplate;
|
|
|
+
|
|
|
+ private String keyFormat = "user:exclude:videoidset:%s";
|
|
|
+
|
|
|
+ public ViewedHistoryFilter(FilterConfigInfo filterConfigInfo,
|
|
|
+ RecommendRequest recommendRequest,
|
|
|
+ User user) {
|
|
|
+ super(filterConfigInfo, recommendRequest, user);
|
|
|
+ historySet = this.loadUserHistory(user);
|
|
|
+ if (historySet == null)
|
|
|
+ historySet = new HashSet<>();
|
|
|
+ }
|
|
|
+
|
|
|
+ public boolean predicate(Candidate candidate, Video video) {
|
|
|
+ return !this.historySet.contains(String.valueOf(video.getVideoId()));
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ public Set<String> loadUserHistory(User user) {
|
|
|
+ String userid = StringUtils.isNotBlank(user.getUid()) ? user.getUid() : user.getMid();
|
|
|
+ if (StringUtils.isBlank(userid)) {
|
|
|
+ return new HashSet<String>();
|
|
|
+ }
|
|
|
+
|
|
|
+ String key = String.format(keyFormat, user.getMid());
|
|
|
+ Set<String> viewedVideoIds = redisTemplate.opsForSet().members(key);
|
|
|
+ if (CollectionUtils.isEmpty(viewedVideoIds)) {
|
|
|
+ // 从mongo取曝光数据
|
|
|
+ Criteria criteria = new Criteria();
|
|
|
+ criteria.and("uid").is(user);
|
|
|
+ Query query = new Query();
|
|
|
+ query.addCriteria(criteria);
|
|
|
+ List<VideoView> list = mongoTemplate.find(query, VideoView.class);
|
|
|
+
|
|
|
+ //TODO 为什么限制最多10000条?是不是限制近几天更合适?
|
|
|
+ if (CollectionUtils.isNotEmpty(list)) {
|
|
|
+ int limit = 10000;
|
|
|
+ for (int i = list.size() - 1; i >= 0 && limit-- > 0; i--) {
|
|
|
+ viewedVideoIds.add(String.valueOf(list.get(i).getVideoId()));
|
|
|
+ }
|
|
|
+
|
|
|
+ // 异步写Redis
|
|
|
+ ThreadPoolFactory.defaultPool().execute(() -> {
|
|
|
+ redisTemplate.executePipelined(new SessionCallback<String>() {
|
|
|
+ @Override
|
|
|
+ public <A, B> String execute(RedisOperations<A, B> redisOperations) throws DataAccessException {
|
|
|
+ SetOperations<String, String> operations =
|
|
|
+ (SetOperations<String, String>) redisOperations.opsForSet();
|
|
|
+ operations.add(key, viewedVideoIds.toArray(new String[viewedVideoIds.size()]));
|
|
|
+ redisTemplate.expire(key, 360 * 3600, TimeUnit.SECONDS);
|
|
|
+ return null;
|
|
|
+ }
|
|
|
+ });
|
|
|
+ });
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ return viewedVideoIds;
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+
|
|
|
+}
|