瀏覽代碼

增加推荐需求

XuShengTao 6 年之前
父節點
當前提交
0b4144e127

+ 2 - 0
src/main/java/com/seec/bok/back/repository/InteractiveCollectRepository.java

@@ -1,6 +1,7 @@
 package com.seec.bok.back.repository;
 
 import com.seec.bok.back.entity.InteractiveCollect;
+import com.seec.bok.back.entity.InteractiveRate;
 import com.seec.bok.back.utils.InteractiveMultiKeys;
 import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
@@ -11,5 +12,6 @@ import java.util.List;
 
 public interface InteractiveCollectRepository extends JpaRepository<InteractiveCollect, InteractiveMultiKeys>, JpaSpecificationExecutor<InteractiveCollect>,QueryByExampleExecutor<InteractiveCollect> {
     List<InteractiveCollect> findAllByUserId(String userId);
+    List<InteractiveCollect> findAllByQuestionIdIn(Collection<String> questionId);
     List<InteractiveCollect> findAllByUserIdAndQuestionIdIn(String userId, Collection<String> questionId);
 }

+ 2 - 1
src/main/java/com/seec/bok/back/repository/InteractiveRateRepository.java

@@ -7,10 +7,11 @@ import org.springframework.data.jpa.repository.JpaRepository;
 import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
 import org.springframework.data.repository.query.QueryByExampleExecutor;
 
+import java.util.Collection;
 import java.util.List;
 
 public interface InteractiveRateRepository extends JpaRepository<InteractiveRate, InteractiveMultiKeys>, JpaSpecificationExecutor<InteractiveRate>,QueryByExampleExecutor<InteractiveRate> {
     List<InteractiveRate> findAllByUserId(String userId);
-
+    List<InteractiveRate> findAllByQuestionIdIn(Collection<String> questionId);
     List<InteractiveRate> findAllByUserIdAndQuestionIdIn(String userId, List<String> questionIdList);
 }

+ 82 - 0
src/main/java/com/seec/bok/service/InteractiveService.java

@@ -2,13 +2,19 @@ package com.seec.bok.service;
 
 import com.seec.bok.back.entity.InteractiveCollect;
 import com.seec.bok.back.entity.InteractiveRate;
+import com.seec.bok.back.entity.Record;
 import com.seec.bok.back.repository.InteractiveCollectRepository;
 import com.seec.bok.back.repository.InteractiveRateRepository;
 import com.seec.bok.back.utils.InteractiveMultiKeys;
+import com.seec.bok.web.dto.PageDTO;
+import com.seec.bok.web.util.GuavaCacheUtil;
+import com.seec.bok.web.vo.InteractionVO;
 import com.seec.bok.web.vo.InteractiveVO;
 import com.seec.bok.web.vo.PageableQuestionListVO;
 import com.seec.bok.web.vo.QuestionVO;
+import com.seec.bok.web.vo.constant.EventType;
 import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.data.domain.Page;
 import org.springframework.data.domain.PageRequest;
 import org.springframework.data.domain.Pageable;
 import org.springframework.stereotype.Service;
@@ -24,6 +30,10 @@ public class InteractiveService {
     private InteractiveRateRepository rateRepository;
     @Autowired
     private QuestionService questionService;
+    @Autowired
+    private GuavaCacheUtil cacheUtils;
+    @Autowired
+    private RecordService recordService;
     public InteractiveRate addRate(String userId,String questionId,Integer rate){
         InteractiveRate ir=new InteractiveRate();
         ir.setQuestionId(questionId);
@@ -90,4 +100,76 @@ public class InteractiveService {
         interactiveRateList.forEach(i->{qid2InteractiveVOS.get(i.getQuestionId()).setRate(i.getRate());});
         return new ArrayList<>(qid2InteractiveVOS.values());
     }
+
+    public List<InteractionVO> getAllInteraction(String knowledgeId) {
+        final List<String> idList = fromKnowledgeIdGetQuestionIds(knowledgeId);
+
+        final List<Record> recordList = recordService.findRecordByUidAndQidAndRidIn(null, idList, null, PageDTO.of(null)).getContent();
+        final List<InteractiveCollect> collectList = collectRepository.findAllByQuestionIdIn(idList);
+        final List<InteractiveRate> rateList = rateRepository.findAllByQuestionIdIn(idList);
+
+        checkList(recordList);
+        checkList(collectList);
+        checkList(rateList);
+
+        List<InteractionVO> list=new ArrayList<>(recordList.size()+collectList.size()+rateList.size());
+
+        for(Record r:recordList){
+            EventType type;
+            if(r.getPass()==null|| !r.getPass()){
+                type=EventType.NOT_PASS;
+            }else{
+                type=EventType.PASS;
+            }
+            String id=r.getUserId()+type+r.getQuestionId();
+            InteractionVO vo=new InteractionVO(id,type,r.getUserId(),r.getQuestionId());
+            list.add(vo);
+        }
+
+        for(InteractiveCollect ic:collectList){
+            EventType type;
+            if(ic.getCollection()!=null&&ic.getCollection()){
+                type=EventType.COLLECT;
+            }else {
+                continue;
+            }
+            String id=ic.getUserId()+type+ic.getQuestionId();
+            InteractionVO vo=new InteractionVO(id,type,ic.getUserId(),ic.getQuestionId());
+            list.add(vo);
+        }
+
+        for(InteractiveRate rate:rateList){
+            EventType type;
+            if(rate.getRate()!=null){
+                type=EventType.RATE;
+            }else {
+                continue;
+            }
+            String id=rate.getUserId()+type+rate.getQuestionId();
+            InteractionVO vo=new InteractionVO(id,type,rate.getUserId(),rate.getQuestionId());
+            list.add(vo);
+        }
+        return list;
+    }
+    private static String CACHE_NAME="Kid2QidS";
+    private List<String> fromKnowledgeIdGetQuestionIds(String knowledgeId){
+
+        final Object ret = (List<String>) cacheUtils.get(CACHE_NAME, knowledgeId);
+        if(ret==null){
+            Pageable pageable =PageDTO.of(null);
+            final PageableQuestionListVO search = questionService.search(null, null, knowledgeId, pageable);
+            final List<String> idList = search.getQuestions().stream().map(QuestionVO::getId).collect(Collectors.toList());
+            cacheUtils.set(CACHE_NAME,knowledgeId,idList);
+            return idList;
+        }else{
+            return (List<String>) ret;
+        }
+
+    }
+    private boolean isEmpty(List list){
+        return list==null||list.size()==0;
+    }
+    private void checkList(List list){
+        if(isEmpty(list)){list=new ArrayList<>();}
+    }
 }

+ 1 - 0
src/main/java/com/seec/bok/service/QuestionService.java

@@ -95,4 +95,5 @@ public class QuestionService {
     public Page<Question> search(QueryBuilder query, Pageable pageable) {
         return questionRepository.search(query, pageable);
     }
+
 }

+ 30 - 0
src/main/java/com/seec/bok/web/controller/InteractionController.java

@@ -0,0 +1,30 @@
+package com.seec.bok.web.controller;
+
+import com.seec.bok.service.InteractiveService;
+import com.seec.bok.web.vo.InteractionVO;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RequestParam;
+import org.springframework.web.bind.annotation.RestController;
+
+import java.util.List;
+
+/** @author Kunduin */
+@RestController
+@RequestMapping("/api/interaction")
+public class InteractionController {
+    @Autowired
+    private InteractiveService interactiveService;
+    @GetMapping("")
+    @Operation(description = "获得全部交互事件")
+    public List<InteractionVO> getAllInteraction(
+            @RequestParam(value = "knowledgeId", required = false)
+                    @Parameter(description = "模糊查找题目")
+                    String knowledgeId) {
+        return interactiveService.getAllInteraction(knowledgeId);
+    }
+
+}

+ 62 - 0
src/main/java/com/seec/bok/web/util/GuavaCacheUtil.java

@@ -0,0 +1,62 @@
+package com.seec.bok.web.util;
+
+import com.google.common.cache.Cache;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.collect.ImmutableMap;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Component;
+
+import java.util.Collection;
+import java.util.Map;
+import java.util.concurrent.TimeUnit;
+import java.util.stream.Collectors;
+
+@Component
+public class GuavaCacheUtil {
+    private Cache<Object, Object> cache;
+
+    @Value("${guavaCache.maximumSize}")
+    private Long maximumSize = 1000L;
+
+    @Value("${guavaCache.expireAfterAccessInSeconds}")
+    private Long expireAfterAccessInSeconds = 1800L;
+
+    @Value("${guavaCache.expireAfterWriteInSeconds}")
+    private Long expireAfterWriteInSeconds = 3600L;
+
+    public GuavaCacheUtil() {
+        CacheBuilder<Object, Object> builder = CacheBuilder.newBuilder();
+        builder.maximumSize(maximumSize);
+        builder.expireAfterAccess(expireAfterAccessInSeconds, TimeUnit.SECONDS);
+        builder.expireAfterWrite(expireAfterWriteInSeconds, TimeUnit.SECONDS);
+        cache = builder.build();
+    }
+
+    public void set(String cacheName, String key, Object value) {
+        cache.put(combineKey(cacheName, key), value);
+    }
+
+    public void setAll(String cacheName, Map<String, Object> putAll) {
+        final Map<String, Object> all = putAll.entrySet().stream().collect(Collectors.toMap(entry -> {
+            return combineKey(cacheName, entry.getKey());
+        }, Map.Entry::getValue));
+        cache.putAll(all);
+    }
+
+    public Object get(String cacheName, String key) {
+        return cache.getIfPresent(combineKey(cacheName, key));
+    }
+
+    public ImmutableMap<Object, Object> multiGet(String cacheName, Collection<String> keys) {
+        Collection<String> body = keys.stream().map(s -> combineKey(cacheName, s)).collect(Collectors.toList());
+        return cache.getAllPresent(body);
+    }
+
+    public void remove(String cacheName, String key) {
+        cache.invalidate(combineKey(cacheName, key));
+    }
+
+    private String combineKey(String cacheName, String key) {
+        return cacheName + ":" + key;
+    }
+}

+ 19 - 0
src/main/java/com/seec/bok/web/vo/InteractionVO.java

@@ -0,0 +1,19 @@
+package com.seec.bok.web.vo;
+
+import com.seec.bok.web.vo.constant.EventType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+
+/** @author Kunduin */
+@Data
+@Builder
+@AllArgsConstructor
+@NoArgsConstructor
+public class InteractionVO {
+    String id;
+    EventType event;
+    String userId;
+    String questionId;
+}

+ 13 - 0
src/main/java/com/seec/bok/web/vo/constant/EventType.java

@@ -0,0 +1,13 @@
+package com.seec.bok.web.vo.constant;
+
+/** @author Kunduin */
+public enum EventType {
+    /** 收集 */
+    COLLECT,
+    /** 评分 */
+    RATE,
+    /** 做对 */
+    PASS,
+    /** 做错 */
+    NOT_PASS
+}

+ 6 - 1
src/main/resources/application.yml

@@ -17,4 +17,9 @@ spring:
 
   servlet:
     multipart:
-      max-file-size: 5MB
+      max-file-size: 5MB
+
+guavaCache:
+  maximumSize: 1000
+  expireAfterAccessInSeconds: 1800
+  expireAfterWriteInSeconds: 1800