丁云鹏 1 年之前
父节点
当前提交
05b391aa3b

+ 8 - 0
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/grpcservice/FeatureGrpcService.java

@@ -31,4 +31,12 @@ public class FeatureGrpcService extends FeatureServiceGrpc.FeatureServiceImplBas
         responseObserver.onNext(response);
         responseObserver.onCompleted();
     }
+
+    @Override
+    public void getAllVideoFeature(GetAllVideoFeatureRequest request,
+                                   StreamObserver<GetAllVideoFeatureResponse> responseObserver) {
+        GetAllVideoFeatureResponse response = videoFeatureService.getAllVideoFeature(request);
+        responseObserver.onNext(response);
+        responseObserver.onCompleted();
+    }
 }

+ 90 - 4
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/UserActionFeature.java

@@ -7,11 +7,97 @@ import lombok.Data;
  */
 @Data
 public class UserActionFeature {
-    private long expCnt;
-    private long clickCnt;
-    private long shareCnt;
-    private long returnCnt;
+    private double exp_cnt;
+    private double click_cnt;
+    private double share_cnt;
+    private double return_cnt;
+
     private double ctr;
     private double str;
     private double rov;
+    private double ros;
+
+    private double ceilLog(Double key) {
+        return Math.ceil(Math.log(key));
+    }
+
+    private double bucketRatioFeature(Double key) {
+        long bucket = Math.round(Math.log(key * 100));
+        if (bucket > 100)
+            bucket = 100;
+        return (double) bucket;
+    }
+
+
+    public void setExp_cnt(Object key) {
+        if (key == null) {
+            this.exp_cnt = 0.0;
+        } else {
+            String formateKey = key.toString().replace("\\N", "-1");
+            this.exp_cnt = ceilLog(Double.valueOf(formateKey));
+        }
+    }
+
+    public void setClick_cnt(Object key) {
+        if (key == null) {
+            this.click_cnt = 0.0;
+        } else {
+            String formateKey = key.toString().replace("\\N", "-1");
+            this.click_cnt = ceilLog(Double.valueOf(formateKey));
+        }
+    }
+
+    public void setShare_cnt(Object key) {
+        if (key == null) {
+            this.share_cnt = 0.0;
+        } else {
+            String formateKey = key.toString().replace("\\N", "-1");
+            this.share_cnt = ceilLog(Double.valueOf(formateKey));
+        }
+    }
+
+    public void setReturn_cnt(Object key) {
+        if (key == null) {
+            this.return_cnt = 0.0;
+        } else {
+            String formateKey = key.toString().replace("\\N", "-1");
+            this.return_cnt = ceilLog(Double.valueOf(formateKey));
+        }
+    }
+
+    public void setCtr(Object key) {
+        if (key == null) {
+            this.ctr = 0.0;
+        } else {
+            String formateKey = key.toString().replace("\\N", "-1");
+            this.ctr = bucketRatioFeature(Double.valueOf(formateKey));
+        }
+    }
+
+    public void setStr(Object key) {
+        if (key == null) {
+            this.str = 0.0;
+        } else {
+            String formateKey = key.toString().replace("\\N", "-1");
+            this.str = bucketRatioFeature(Double.valueOf(formateKey));
+        }
+    }
+
+    public void setRov(Object key) {
+        if (key == null) {
+            this.rov = 0.0;
+        } else {
+            String formateKey = key.toString().replace("\\N", "-1");
+            this.rov = bucketRatioFeature(Double.valueOf(formateKey));
+        }
+    }
+
+    public void setRos(Object key) {
+        if (key == null) {
+            this.ros = 0.0;
+        } else {
+            String formateKey = key.toString().replace("\\N", "-1");
+            this.ros = bucketRatioFeature(Double.valueOf(formateKey));
+        }
+    }
 }

+ 58 - 8
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/UserFeature.java

@@ -7,18 +7,68 @@ import lombok.Data;
  */
 @Data
 public class UserFeature {
-    private String mid;
     private String uid;
     // 当天统计量信息
-    private UserActionFeature day1CntFeature;
+    private UserActionFeature day1_cnt_features;
     // 3天内统计量
-    private UserActionFeature day3CntFeature;
+    private UserActionFeature day3_cnt_features;
     // 7天内统计量
-    private UserActionFeature day7CntFeature;
+    private UserActionFeature day7_cnt_features;
     // 3个月统计量
-    private UserActionFeature month3CntFeature;
+    private UserActionFeature month3_cnt_features;
     // 用户行为周期
-    private String userCycleBucket7days;
-    private String userCycleBucket30days;
-    private String userShareBucket30days;
+    private String user_cycle_bucket_7days;
+    private String user_cycle_bucket_30days;
+    private String user_share_bucket_30days;
+
+    public void setUid(String key){
+        this.uid = key;
+        if(key == null)
+            this.uid = "0";
+    }
+
+
+    public void setDay1_cnt_features(UserActionFeature key){
+        this.day1_cnt_features = key;
+        if(key == null)
+            this.day1_cnt_features = new UserActionFeature();
+    }
+
+    public void setDay3_cnt_features(UserActionFeature key){
+        this.day3_cnt_features = key;
+        if(key == null)
+            this.day3_cnt_features = new UserActionFeature();
+    }
+
+    public void setDay7_cnt_features(UserActionFeature key){
+        this.day7_cnt_features = key;
+        if(key == null)
+            this.day7_cnt_features = new UserActionFeature();
+    }
+
+    public void setMonth3_cnt_features(UserActionFeature key) {
+        this.month3_cnt_features = key;
+        if(key == null)
+            this.month3_cnt_features = new UserActionFeature();
+    }
+
+
+    public void setUser_cycle_bucket_7days(String key){
+        this.user_cycle_bucket_7days = key;
+        if(key == null)
+            this.user_cycle_bucket_7days = "0";
+    }
+
+    public void setUser_cycle_bucket_30days(String key){
+        this.user_cycle_bucket_30days = key;
+        if(key == null)
+            this.user_cycle_bucket_30days = "0";
+    }
+
+    public void setUser_share_bucket_30days(String key){
+        this.user_share_bucket_30days = key;
+        if(key == null)
+            this.user_share_bucket_30days = "0";
+    }
+
 }

+ 105 - 4
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/model/VideoFeature.java

@@ -8,18 +8,119 @@ import lombok.Data;
 @Data
 public class VideoFeature {
     private String videoId;
+
     private String upId;
+
     private String tags;
+
+    /**
+     * 有多个标题,暂时不会用到所以先不处理
+     * @since 2023-12-05
+     */
+    private String title;
+
+    private String titleLength;
+
     private String playLength;
+
     private String totalTime;
+
     private String daysSinceUpload;
 
+
     // 当天统计量信息
-    private UserActionFeature videoDay1CntFeature;
+    private UserActionFeature day1_cnt_features;
     // 3天内统计量
-    private UserActionFeature videoDay3CntFeature;
+    private UserActionFeature day3_cnt_features;
     // 7天内统计量
-    private UserActionFeature videoDay7CntFeature;
+    private UserActionFeature day7_cnt_features;
     // 3个月统计量
-    private UserActionFeature videoMonth3CntFeature;
+    private UserActionFeature month3_cnt_features;
+
+
+    public void setVideoId(String key){
+        if(key == null){
+            this.videoId = "0";
+        } else {
+            this.videoId = key;
+        }
+    }
+
+    public void setUpId(String key){
+        if(key == null){
+            this.upId = "0";
+        } else {
+            this.upId = key;
+        }
+    }
+
+    public void setTags(String key){
+        if(key == null){
+            this.tags = "0";
+        } else {
+            this.tags = key;
+        }
+    }
+
+    public void setTitle(String key){
+        if(key == null){
+            this.title = "0";
+        } else {
+            this.title = key;
+        }
+    }
+
+
+    public void setDay1_cnt_features(UserActionFeature feature){
+        this.day1_cnt_features = feature;
+    }
+
+
+    public void setDay3_cnt_features(UserActionFeature feature){
+        this.day3_cnt_features = feature;
+
+    }
+
+    public void setDay7_cnt_features(UserActionFeature feature){
+        this.day7_cnt_features = feature;
+
+    }
+
+    public void setMonth3_cnt_features(UserActionFeature feature){
+        this.month3_cnt_features= feature;
+
+    }
+
+    public void setTitleLength(String key) {
+        if(key == null){
+            this.titleLength = "0";
+        } else {
+            this.titleLength = key;
+        }
+    }
+
+
+    public void setDaysSinceUpload(String key) {
+        if(key == null){
+            this.daysSinceUpload = "0";
+        } else {
+            this.daysSinceUpload = key;
+        }
+    }
+
+    public void setPlayLength(String key) {
+        if(key == null){
+            this.playLength = "0";
+        } else {
+            this.playLength = key;
+        }
+    }
+
+    public void setTotalTime(String key) {
+        if(key == null){
+            this.totalTime = "0";
+        } else {
+            this.totalTime = key;
+        }
+    }
 }

+ 55 - 1
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/AbstractFeatureService.java

@@ -10,6 +10,9 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Qualifier;
 import org.springframework.data.redis.core.RedisTemplate;
 
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
 import java.util.concurrent.TimeUnit;
 import java.util.function.Function;
 
@@ -62,6 +65,11 @@ public abstract class AbstractFeatureService<K, V> {
                     public V load(K key) {
                         return AbstractFeatureService.this.load(key);
                     }
+
+                    @Override
+                    public Map<K, V> loadAll(Iterable<? extends K> keys) {
+                        return AbstractFeatureService.this.loadAll(keys);
+                    }
                 });
     }
 
@@ -87,7 +95,7 @@ public abstract class AbstractFeatureService<K, V> {
     }
 
     private V getFromCache(K key) {
-        String redisKey = keyFunc.apply(key);
+        String redisKey = cacheKey(key);
         String value = redisTemplate.opsForValue().get(redisKey);
         return JSONUtils.fromJson(value, typeToken, null);
     }
@@ -110,6 +118,45 @@ public abstract class AbstractFeatureService<K, V> {
         redisTemplate.opsForValue().set(cacheKey, cacheValue, expire, TimeUnit.SECONDS);
     }
 
+    private Map<K, V> loadAll(Iterable<? extends K> keyIte) {
+
+        Map<K,V> featureMap = getFromCache(keyIte);
+        if (feature == null) {
+            feature = getFromSource(keyIte);
+            // TODO 可异步
+            saveToCache();
+        }
+        return feature;
+    }
+
+    private V getFromCache(Iterable<? extends K> keyIte) {
+
+        Iterator<? extends K> ite = keyIte.iterator();
+        while (ite.hasNext()) {
+            keys.add(ite.next());
+        }
+        String redisKey = cacheKey(key);
+        String value = redisTemplate.opsForValue().get(redisKey);
+        return JSONUtils.fromJson(value, typeToken, null);
+    }
+
+    private V getFromSource(Iterable<? extends K> keyIte) {
+        String sourceKey = cacheKey(key);
+        String value = tairTemplate.opsForValue().get(sourceKey);
+        return JSONUtils.fromJson(value, typeToken, null);
+    }
+
+    private void saveToCache(Map<K, V> map) {
+        String cacheKey = cacheKey(key);
+        String cacheValue = value == null
+                ? emptyData
+                : JSONUtils.toJson(value);
+        long expire = value == null
+                ? emptyDataExpire
+                : defaultExpire;
+        // TODO 评估过期时间
+        redisTemplate.opsForValue().set(cacheKey, cacheValue, expire, TimeUnit.SECONDS);
+    }
 
     private String cacheKey(K key) {
         return keyFunc.apply(key);
@@ -132,4 +179,11 @@ public abstract class AbstractFeatureService<K, V> {
         redisTemplate.delete(cacheKey);
     }
 
+    protected List<V> getAll(List<K> videoIds) {
+        try {
+            cache.getAll(videoIds);
+        } catch (Exception e) {
+
+        }
+    }
 }

+ 1 - 1
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/UserFeatureService.java

@@ -21,7 +21,7 @@ public class UserFeatureService extends AbstractFeatureService<String, UserFeatu
         super.emptyData = "{}";
         super.emptyDataExpire = 60;
         super.defaultExpire = 7200;
-        super.keyFunc = k -> String.format("user:meta:%s", k);
+        super.keyFunc = k -> String.format("user:%s", k);
         super.typeToken = new TypeToken<UserFeature>() {
         };
 

+ 30 - 1
recommend-feature-service/src/main/java/com/tzld/piaoquan/recommend/feature/service/VideoFeatureService.java

@@ -3,12 +3,18 @@ package com.tzld.piaoquan.recommend.feature.service;
 import com.google.common.reflect.TypeToken;
 import com.tzld.piaoquan.recommend.feature.model.VideoFeature;
 import com.tzld.piaoquan.recommend.feature.model.common.Result;
+import com.tzld.piaoquan.recommend.feature.model.feature.GetAllVideoFeatureRequest;
+import com.tzld.piaoquan.recommend.feature.model.feature.GetAllVideoFeatureResponse;
 import com.tzld.piaoquan.recommend.feature.model.feature.GetVideoFeatureRequest;
 import com.tzld.piaoquan.recommend.feature.model.feature.GetVideoFeatureResponse;
+import com.tzld.piaoquan.recommend.feature.util.CommonCollectionUtils;
 import com.tzld.piaoquan.recommend.feature.util.JSONUtils;
 import lombok.extern.slf4j.Slf4j;
 import org.apache.commons.lang.StringUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.util.CollectionUtils;
+
+import java.util.List;
 
 /**
  * @author dyp
@@ -21,7 +27,7 @@ public class VideoFeatureService extends AbstractFeatureService<String, VideoFea
         super.emptyData = "{}";
         super.emptyDataExpire = 60;
         super.defaultExpire = 7200;
-        super.keyFunc = k -> String.format("video:meta:%s", k);
+        super.keyFunc = k -> String.format("video:%s", k);
         super.typeToken = new TypeToken<VideoFeature>() {
         };
 
@@ -29,6 +35,7 @@ public class VideoFeatureService extends AbstractFeatureService<String, VideoFea
         int refreshAfterWrite = 60;
         int expireAfterWrite = 60;
         int expireAfterAccess = 60;
+
         initLocalCache(maximumSize, refreshAfterWrite, expireAfterWrite, expireAfterAccess);
     }
 
@@ -53,4 +60,26 @@ public class VideoFeatureService extends AbstractFeatureService<String, VideoFea
         }, null);
         super.save(videoFeature.getVideoId(), videoFeature);
     }
+
+    public GetAllVideoFeatureResponse getAllVideoFeature(GetAllVideoFeatureRequest request) {
+        // TODO
+        if (request.getVideoIdCount() == 0) {
+            return GetAllVideoFeatureResponse.newBuilder()
+                    .setResult(Result.newBuilder().setCode(1))
+                    .build();
+        }
+        List<String> videoIds = request.getVideoIdList();
+
+        List<VideoFeature> videoFeatures = super.getAll(videoIds);
+        if (CollectionUtils.isEmpty(videoFeatures)) {
+            return GetAllVideoFeatureResponse.newBuilder()
+                    .setResult(Result.newBuilder().setCode(1))
+                    .build();
+        }
+
+        return GetAllVideoFeatureResponse.newBuilder()
+                .setResult(Result.newBuilder().setCode(1))
+                .addAllVideoFeature(CommonCollectionUtils.toList(videoFeatures, FeatureConverter::convert))
+                .build();
+    }
 }