Browse Source

add userTag search

sunhui 1 year ago
parent
commit
b3171ec445

+ 0 - 1
build.gradle

@@ -29,7 +29,6 @@ dependencies {
     }
     testImplementation 'org.springframework.kafka:spring-kafka-test'
 
-    implementation "com.alicp.jetcache:jetcache-starter-redis:2.4.4"
     implementation "commons-io:commons-io:2.4"
     implementation "joda-time:joda-time:2.9.9"
     implementation "commons-beanutils:commons-beanutils:1.9.4"

+ 6 - 1
src/main/java/com/finogeeks/swan/dataanalysis/api/HxAnalysisController.java

@@ -2,9 +2,11 @@ package com.finogeeks.swan.dataanalysis.api;
 
 import com.finogeeks.swan.dataanalysis.client.HxServiceClient;
 import com.finogeeks.swan.dataanalysis.client.UacServiceClient;
+import com.finogeeks.swan.dataanalysis.entity.tag.UserTag;
 import com.finogeeks.swan.dataanalysis.entity.vo.huaxi.*;
 import com.finogeeks.swan.dataanalysis.exception.DataCubeException;
 import com.finogeeks.swan.dataanalysis.service.HuaXiService;
+import com.finogeeks.swan.dataanalysis.service.UserTagService;
 import com.finogeeks.swan.dataanalysis.service.impl.HuaxiBindingService;
 import com.finogeeks.swan.dataanalysis.util.TidHelper;
 import lombok.extern.slf4j.Slf4j;
@@ -28,13 +30,15 @@ public class HxAnalysisController {
     private final HxServiceClient hxClient;
     private final UacServiceClient uacClient;
     private final HuaxiBindingService bindingService;
+    private final UserTagService userTagService;
 
     @Autowired
-    public HxAnalysisController(HuaXiService huaXiService, HxServiceClient hxServiceClient, UacServiceClient uacClient, HuaxiBindingService bindingService) {
+    public HxAnalysisController(HuaXiService huaXiService, HxServiceClient hxServiceClient, UacServiceClient uacClient, HuaxiBindingService bindingService, UserTagService userTagService) {
         this.huaXiService = huaXiService;
         this.hxClient = hxServiceClient;
         this.uacClient = uacClient;
         this.bindingService = bindingService;
+        this.userTagService = userTagService;
     }
 
     /**
@@ -487,4 +491,5 @@ public class HxAnalysisController {
         }
         return huaXiService.getConnection2nd(operator);
     }
+
 }

+ 54 - 0
src/main/java/com/finogeeks/swan/dataanalysis/api/UserTagController.java

@@ -0,0 +1,54 @@
+package com.finogeeks.swan.dataanalysis.api;
+
+import com.finogeeks.swan.dataanalysis.entity.tag.UserTag;
+import com.finogeeks.swan.dataanalysis.exception.DataCubeException;
+import com.finogeeks.swan.dataanalysis.service.UserTagService;
+import com.finogeeks.swan.dataanalysis.util.TidHelper;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.http.HttpStatus;
+import org.springframework.util.StringUtils;
+import org.springframework.web.bind.annotation.*;
+
+/**
+ * @author sunhui
+ *
+ */
+@Slf4j
+@RestController
+@RequestMapping("/tags")
+public class UserTagController {
+    private final UserTagService userTagService;
+
+    @Autowired
+    public UserTagController(UserTagService userTagService) {
+        this.userTagService = userTagService;
+    }
+
+    /**
+     * @api {GET} /api/v1/swan/datacube/tags/recommendation  [C/S] 获取用户的推荐标签
+     * @apiGroup data-analysis
+     * @apiVersion __API_VERSION__
+     * @apiPrivate
+     * @apiHeader {String} X-Consumer-Custom-ID="@xxx:finogeeks.club"
+     * @apiParam (QueryParam)   {String}   userId   用户id
+     * @apiSuccessExample {json} Success Status:
+     * HTTP/1.1 200
+     * <pre>
+     * {
+     *   "userId":  "userId",
+     *   "tags":  ["111","222","333"]
+     * }
+     * </pre>
+     * @apiErrorExample Error Status:
+     * HTTP/1.1 500
+     */
+    @GetMapping("/recommendation")
+    public UserTag test(@RequestParam(value = "userId") String userId) {
+        if(StringUtils.isEmpty(userId)) {
+            throw new DataCubeException(HttpStatus.BAD_REQUEST,"fc_error","缺少staffId字段");
+        }
+        return userTagService.getTopTagsByUserIn90D(userId, TidHelper.get().getTid(), 5);
+    }
+
+}

+ 17 - 0
src/main/java/com/finogeeks/swan/dataanalysis/entity/tag/UserTag.java

@@ -0,0 +1,17 @@
+package com.finogeeks.swan.dataanalysis.entity.tag;
+
+import lombok.Data;
+
+import java.util.HashSet;
+import java.util.Set;
+
+
+@Data
+public class UserTag {
+    private String userId;
+    private Set<String> tags = new HashSet<>();
+
+    public void addTags(String tagId) {
+        tags.add(tagId);
+    }
+}

+ 7 - 0
src/main/java/com/finogeeks/swan/dataanalysis/service/UserTagService.java

@@ -0,0 +1,7 @@
+package com.finogeeks.swan.dataanalysis.service;
+
+import com.finogeeks.swan.dataanalysis.entity.tag.UserTag;
+
+public interface UserTagService {
+    UserTag getTopTagsByUserIn90D(String userId, String tid, int number);
+}

+ 1 - 1
src/main/java/com/finogeeks/swan/dataanalysis/service/impl/AnalysisServiceImpl.java

@@ -41,7 +41,7 @@ import java.util.stream.Collectors;
 public class AnalysisServiceImpl implements AnalysisService {
 
     //用户访问记录表
-    private static final String RETAIL_APP_TYPE = "RETAIL";
+    public static final String RETAIL_APP_TYPE = "RETAIL";
     private static final String STAFF_APP_TYPE = "STAFF";
     //微信小程序的数据上报
     private static final String WECHAT_MINI = "Wechat";

+ 75 - 0
src/main/java/com/finogeeks/swan/dataanalysis/service/impl/UserTagServiceImpl.java

@@ -0,0 +1,75 @@
+package com.finogeeks.swan.dataanalysis.service.impl;
+
+import com.finogeeks.swan.dataanalysis.entity.tag.UserTag;
+import com.finogeeks.swan.dataanalysis.service.UserTagService;
+import com.finogeeks.swan.dataanalysis.util.DateUtil;
+import lombok.extern.slf4j.Slf4j;
+import org.elasticsearch.action.search.SearchResponse;
+import org.elasticsearch.index.query.BoolQueryBuilder;
+import org.elasticsearch.index.query.QueryBuilders;
+import org.elasticsearch.index.query.RangeQueryBuilder;
+import org.elasticsearch.search.aggregations.AbstractAggregationBuilder;
+import org.elasticsearch.search.aggregations.AggregationBuilders;
+import org.elasticsearch.search.aggregations.BucketOrder;
+import org.elasticsearch.search.aggregations.bucket.terms.Terms;
+import org.elasticsearch.search.aggregations.metrics.sum.Sum;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.elasticsearch.core.ElasticsearchTemplate;
+import org.springframework.stereotype.Service;
+
+import static com.finogeeks.swan.dataanalysis.service.impl.AnalysisServiceImpl.RETAIL_APP_TYPE;
+
+@Slf4j
+@Service
+public class UserTagServiceImpl implements UserTagService {
+
+    private static final String USER_TAGS_INDEX = "swan_data_analysis_tag_user*";
+
+    private final ElasticsearchTemplate esTemplate;
+
+    @Autowired
+    public UserTagServiceImpl(ElasticsearchTemplate esTemplate) {
+        this.esTemplate = esTemplate;
+    }
+
+
+    @Override
+    public UserTag getTopTagsByUserIn90D(String userId, String tid, int number) {
+
+        RangeQueryBuilder timeDurationQuery = new RangeQueryBuilder("update_time")
+                .gte(DateUtil.get90DayAgoMillis());
+        BoolQueryBuilder query = QueryBuilders.boolQuery();
+        query.filter(QueryBuilders.termQuery("tid.keyword", tid))
+                .filter(QueryBuilders.termQuery("app_type.keyword", RETAIL_APP_TYPE))
+                .filter(QueryBuilders.termQuery("user_id.keyword", userId))
+                .filter(timeDurationQuery);
+
+        AbstractAggregationBuilder agg = AggregationBuilders
+                .terms("tag_id").field("tag_id")
+                .order(BucketOrder.compound(BucketOrder.aggregation("score", false)))
+                .subAggregation(AggregationBuilders.sum("score").field("score"));
+
+
+        SearchResponse searchRes = esTemplate.getClient().prepareSearch(USER_TAGS_INDEX)
+                .setQuery(query).addAggregation(agg).execute().actionGet();
+
+        UserTag userTag = new UserTag();
+        userTag.setUserId(userId);
+        double score = 0; //上一个的score
+        int count = 0; //取的个数
+        Terms tms = searchRes.getAggregations().get("tag_id");
+        for (Terms.Bucket tbb : tms.getBuckets()) {
+            count++;
+            //获取count的和
+            Sum sum = tbb.getAggregations().get("score");
+            String tagId = tbb.getKeyAsString();
+            //如果已经有number个了,并且下一个和上一个不相等,直接break
+            if(count > number && sum.getValue() < score) {
+                break;
+            }
+            score = sum.getValue();
+            userTag.addTags(tagId);
+        }
+        return userTag;
+    }
+}

+ 5 - 0
src/main/java/com/finogeeks/swan/dataanalysis/util/DateUtil.java

@@ -16,6 +16,7 @@ import java.util.TimeZone;
 public class DateUtil {
 
     public static final Long YEAR_DURATION = 366 * 24 * 3600 * 1000L;
+    public static final Long NINE_MONTH = 90 * 24 * 3600 * 1000L;
 
     /**
      * 获取当天的零点零分的时间戳
@@ -133,6 +134,10 @@ public class DateUtil {
         return startTime <= endTime && (endTime - startTime) <= YEAR_DURATION;
     }
 
+    public static long get90DayAgoMillis() {
+        return System.currentTimeMillis() - NINE_MONTH;
+    }
+
     public static void main(String[] args) {
         System.out.println(getTodayStartTime());
         System.out.println(timestamp2MinStr(1588118400000L));

+ 1 - 1
src/main/resources/application.yaml

@@ -21,7 +21,7 @@ spring:
       #      repositories:
       #        enabled: false
       cluster-name: efk-cluster
-      cluster-nodes: 10.0.209.61:14727,10.0.209.61:14729,10.0.209.61:14728
+      cluster-nodes: 10.0.10.101:14726,10.0.10.101:14728,10.0.10.101:14729
   #      cluster-nodes: efk-elasticsearch.efk:9300
   kafka:
     bootstrap-servers: 127.0.0.1:9092