diff --git a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/RedisUtils.java b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/RedisUtils.java index 2fcabf5d57..309cb9192e 100644 --- a/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/RedisUtils.java +++ b/epmet-commons/epmet-commons-tools/src/main/java/com/epmet/commons/tools/redis/RedisUtils.java @@ -357,6 +357,18 @@ public class RedisUtils { return typedTuples; } + public Set zReverseRange(String key, long start, long end, Class clazz) { + Set objects = redisTemplate.opsForZSet().reverseRange(key, start, end); + if(CollectionUtils.isEmpty(objects)) return null; + return objects.stream().map(o->{ + try { + T target = clazz.newInstance(); + BeanUtils.copyProperties(o, target); + return target; + }catch (Exception e){throw new RenException("convert error");} + }).collect(Collectors.toSet()); + } + /** * @Description 标签使用数量缓存更新 * @param key diff --git a/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/dao/IssueProjectTagDictDao.java b/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/dao/IssueProjectTagDictDao.java index 9fa8ef840d..8439b7d940 100644 --- a/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/dao/IssueProjectTagDictDao.java +++ b/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/dao/IssueProjectTagDictDao.java @@ -92,10 +92,41 @@ public interface IssueProjectTagDictDao extends BaseDao selectTagByCategory(@Param("categories") List categories,@Param("customerId") String customerId,@Param("isDefault")String isDefault); + List selectTagByCategory(@Param("categories") List categories,@Param("customerId") String customerId,@Param("targetCustomerId") String targetCustomerId); + + /** + * @Description 查询客户下的标签数量 + * @param customerId + * @return int + * @author wangc + * @date 2021.03.23 16:51 + */ + int selectCountByCustomerId(@Param("customerId") String customerId); + + /** + * @Description 查询客户下自定义标签 + * @param customerId + * @return java.util.List + * @author wangc + * @date 2021.03.23 16:56 + */ + List selectCustomizedByCustomerId(@Param("customerId") String customerId); + + /** + * @Description 根据传入的二级分类Id查询默认标签 + * 当categories为空时,查询全部默认分类的标签,排序规则:先按照二级分类的上级分类的Sort排序(asc),然后按照二级分类的Sort排序(asc),然后按照标签名拼音排序 + * 当categories不为空时,按照传入的二级分类的顺序排序,然后按照标签名拼音排序 + * @param customerId + * @param categories + * @return java.util.List + * @author wangc + * @date 2021.03.23 15:19 + */ + List selectDefault(@Param("customerId") String customerId,@Param("categories") List categories); /** * @Description 根据客户Id和标签Id集合查询标签的基础信息(标签名、标签码,标签所属分类) + * 不管标签是否被禁用,都可以更新热度,因此这个查询不能加是否禁用的限制 * @param customerId * @param tagIds * @return java.util.List diff --git a/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/redis/IssueProjectTagDictRedis.java b/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/redis/IssueProjectTagDictRedis.java index 33896d5b16..8424fa7ec4 100644 --- a/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/redis/IssueProjectTagDictRedis.java +++ b/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/redis/IssueProjectTagDictRedis.java @@ -29,6 +29,7 @@ import com.epmet.dto.result.IssueCategoryTagResultDTO; import com.epmet.entity.IssueProjectCategoryDictEntity; import com.epmet.entity.IssueProjectTagDictEntity; import com.epmet.service.IssueProjectCategoryDictService; +import com.epmet.service.IssueProjectTagDictService; import com.epmet.utils.ModuleConstants; import com.fasterxml.jackson.databind.ObjectMapper; import lombok.extern.slf4j.Slf4j; @@ -65,6 +66,8 @@ public class IssueProjectTagDictRedis { private IssueProjectCategoryDictDao categoryDictDao; @Autowired private IssueProjectCategoryDictService categoryDictService; + @Autowired + private IssueProjectTagDictService tagDictService; public void delete(Object[] ids) { } @@ -101,12 +104,10 @@ public class IssueProjectTagDictRedis { boolean ifOtherOnly = null == otherCategory ? false : (!CollectionUtils.isEmpty(category) && category.size() == NumConstant.ONE && category.contains(otherCategory.getId()) ? true : false); Map> result = new HashMap<>(); - - List _default = poolDao.selectTagByCategory(ifOtherOnly || CollectionUtils.isEmpty(category) ? null : category, customerId, NumConstant.ZERO_STR);//默认 + //传入的categories不会只包含"其他"这个分类,因为情况下ifOtherOnly为true,直接传入null + List _default = poolDao.selectDefault(customerId,ifOtherOnly ? null : category); if(!CollectionUtils.isEmpty(_default)){ - result.put(ModuleConstants.DEFAULT_TAG_CATEGORY_NAME,_default.stream().map(o -> { - IssueCategoryTagResultDTO tag = ConvertUtils.sourceToTarget(o,IssueCategoryTagResultDTO.class); - tag.setName(o.getTagName()); return tag;}).collect(Collectors.toList())); + result.put(ModuleConstants.DEFAULT_TAG_CATEGORY_NAME,_default); }else log.error("there is no default tag data in database , customerId : {}",customerId); @@ -127,16 +128,19 @@ public class IssueProjectTagDictRedis { result.put(ModuleConstants.CUSTOMIZED_TAG_CATEGORY_NAME,customizedResult); } - //默认、自定义标签,只要有一个是空就触发补偿 - //不信任缓存数据 - if(!CollectionUtils.isEmpty(result) && !CollectionUtils.isEmpty(result.get(ModuleConstants.DEFAULT_TAG_CATEGORY_NAME)) + + //默认、自定义标签,只要有一个是空就触发补偿 + //不信任缓存数据 + if(!CollectionUtils.isEmpty(result) && !CollectionUtils.isEmpty(result.get(ModuleConstants.DEFAULT_TAG_CATEGORY_NAME)) && !CollectionUtils.isEmpty(result.get(ModuleConstants.CUSTOMIZED_TAG_CATEGORY_NAME))) return result; + + log.warn("fetch customer govern tag cache blankly,customerId:{},now begin compensation...", customerId); - Map> compensate = compensate(customerId, category, ifOtherOnly); + Map> compensate = compensate(customerId, category, ifOtherOnly,result); if (CollectionUtils.isEmpty(compensate)) { log.error("compensation failure or there is no tag data in database!!"); @@ -235,7 +239,7 @@ public class IssueProjectTagDictRedis { log.warn("fetch customer govern tag cache blankly,customerId:{},now begin compensation...", customerId); - Map> compensate = compensate(customerId, category, ifOtherOnly); + Map> compensate = compensate(customerId, category, ifOtherOnly,null); if (CollectionUtils.isEmpty(compensate)) { log.error("compensation failure or there is no tag data in database!!"); @@ -249,10 +253,7 @@ public class IssueProjectTagDictRedis { /** - * @Description category为空,则补偿全部,返回默认标签和自定义标签,补偿全部 - * category仅包含"其他"这个分类的Id时,返回同上,补偿全部 - * category不为空且不只有"其他"这个分类的Id时,则返回并补偿集合中的类别标签以及自定义标签 - * 默认标签不按照热度排序,自定义标签按照热度排序 + * @Description 如果之前查询的结果为空,说明默认与自定义都没有 * * * @param customerId @@ -261,17 +262,38 @@ public class IssueProjectTagDictRedis { * @author wangc * @date 2020.12.10 09:34 */ - public Map> compensate(String customerId,List category,boolean ifOtherOnly){ - + public Map> compensate(String customerId,List category,boolean ifOtherOnly,Map> preResult){ - List db = poolDao.selectTagByCategory(ifOtherOnly || CollectionUtils.isEmpty(category) ? null : category, customerId, null); + List db = new LinkedList<>(); - if(CollectionUtils.isEmpty(db) && (ifOtherOnly || CollectionUtils.isEmpty(category))){ + if(CollectionUtils.isEmpty(preResult) || CollectionUtils.isEmpty(preResult.get(ModuleConstants.DEFAULT_TAG_CATEGORY_NAME))){ CategoryTagInitFormDTO customerIdParam = new CategoryTagInitFormDTO(); customerIdParam.setCustomerId(customerId); - categoryDictService.init(customerIdParam); - db = poolDao.selectTagByCategory(ifOtherOnly || CollectionUtils.isEmpty(category) ? null : category, customerId, null); + if(ifOtherOnly || CollectionUtils.isEmpty(category)) { + //补偿全部默认标签 + categoryDictService.init(customerIdParam); + db.addAll(poolDao.selectTagListByCustomer(customerId)); + }else{ + if(NumConstant.ZERO <= poolDao.selectCountByCustomerId(customerId)){ + categoryDictService.init(customerIdParam); + }else{ + //只插入category中的标签 + tagDictService.insertBatch(poolDao.selectTagByCategory(category,"default",customerId)); + db.addAll(poolDao.selectTagsByCustomerIdAndTagIds(customerId,category)); + } + } + } + + if(CollectionUtils.isEmpty(preResult) || CollectionUtils.isEmpty(preResult.get(ModuleConstants.CUSTOMIZED_TAG_CATEGORY_NAME))){ + //先去数据库查询自定义,为空则是最终结果,不为空则补偿 + List customizedTags = poolDao.selectCustomizedByCustomerId(customerId); + if(!CollectionUtils.isEmpty(customizedTags)){ + db.addAll(customizedTags); + } } + + + // key -> redisKey // value -> [key : score ; value : object] Map>> fulfilled = new HashMap<>(); @@ -310,9 +332,12 @@ public class IssueProjectTagDictRedis { Map> result = new HashMap<>(); //默认标签:按照分类排序 Mapper返回的查询结果是有序的 - result.put(ModuleConstants.DEFAULT_TAG_CATEGORY_NAME,CollectionUtils.isEmpty(db) ? null : db.stream().filter(o -> !StringUtils.equals(ModuleConstants.CUSTOMIZED_TAG_CATEGORY_NAME,o.getCategoryId())).map(entity -> { - IssueCategoryTagResultDTO tag = ConvertUtils.sourceToTarget(entity,IssueCategoryTagResultDTO.class); - tag.setName(entity.getTagName()); return tag;}).collect(Collectors.toList())); + //result.put(ModuleConstants.DEFAULT_TAG_CATEGORY_NAME,CollectionUtils.isEmpty(db) ? null : db.stream().filter(o -> !StringUtils.equals(ModuleConstants.CUSTOMIZED_TAG_CATEGORY_NAME,o.getCategoryId())).map(entity -> { + // IssueCategoryTagResultDTO tag = ConvertUtils.sourceToTarget(entity,IssueCategoryTagResultDTO.class); + // tag.setName(entity.getTagName()); return tag;}).collect(Collectors.toList())); + result.put(ModuleConstants.DEFAULT_TAG_CATEGORY_NAME,poolDao.selectDefault(customerId,ifOtherOnly ? null : category)); + + //自定义标签:按照热度排序 sorted(Comparator.comparing(IssueProjectTagDictEntity :: getIssueUseCount).reversed()) result.put(ModuleConstants.CUSTOMIZED_TAG_CATEGORY_NAME,CollectionUtils.isEmpty(db) ? null : db.stream().filter(o -> StringUtils.equals(ModuleConstants.CUSTOMIZED_TAG_CATEGORY_NAME,o.getCategoryId())).sorted(Comparator.comparing(IssueProjectTagDictEntity :: getIssueUseCount).reversed()).map(entity -> { IssueCategoryTagResultDTO tag = ConvertUtils.sourceToTarget(entity,IssueCategoryTagResultDTO.class); @@ -388,7 +413,42 @@ public class IssueProjectTagDictRedis { * @date 2021.03.22 16:20 */ public void updateTagAvailabilityBySecondCategoryIds(String customerId,ListsecondCategoryIds,String availableFlag){ + if(CollectionUtils.isEmpty(secondCategoryIds)) return; + secondCategoryIds.forEach(cid -> { + String key = GovIssueRedisKeys.getGovernmentTagKey(customerId, cid); + + Set> tagTuples = + redisUtils.zReverseRangeWithScores(key, NumConstant.ZERO_L, (long) (NumConstant.ONE_NEG)); + + if(!CollectionUtils.isEmpty(tagTuples)){ + Map> heatMap = new HashMap<>(); + tagTuples.forEach(tuple -> { + Set queue = heatMap.get(tuple.getValue()); + if((CollectionUtils.isEmpty(queue))) queue = new HashSet<>(); + IssueCategoryTagResultDTO ele = parseObject(tuple.getValue(), IssueCategoryTagResultDTO.class); + ele.setIsDisable(availableFlag); + queue.add(ele); + heatMap.put((Double) tuple.getValue(),queue); + }); + List customizedResult = new LinkedList<>(); + heatMap.keySet().stream().sorted(Comparator.reverseOrder()).collect(Collectors.toList()).forEach(count -> { + customizedResult.addAll(heatMap.get(count)); + }); + + redisUtils.delete(key); + redisTemplate.executePipelined((RedisCallback) connection -> { + heatMap.forEach((score,set) -> { + set.forEach(o -> { + connection.zSetCommands().zIncrBy(redisTemplate.getKeySerializer().serialize(key), + score , + redisTemplate.getValueSerializer().serialize(o)); + }); + }); + return null; + }); + } + }); } public T parseObject(Object o,Class clazz){ diff --git a/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/service/impl/IssueProjectCategoryDictServiceImpl.java b/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/service/impl/IssueProjectCategoryDictServiceImpl.java index 006568d0e2..5bdf0a58fe 100644 --- a/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/service/impl/IssueProjectCategoryDictServiceImpl.java +++ b/epmet-module/gov-issue/gov-issue-server/src/main/java/com/epmet/service/impl/IssueProjectCategoryDictServiceImpl.java @@ -40,6 +40,7 @@ import com.epmet.feign.GovProjectOpenFeignClient; import com.epmet.feign.OperCrmOpenFeignClient; import com.epmet.project.dto.result.ProjectCategoryDictResultDTO; import com.epmet.redis.IssueProjectCategoryDictRedis; +import com.epmet.redis.IssueProjectTagDictRedis; import com.epmet.service.IssueProjectCategoryDictService; import com.epmet.service.IssueProjectTagDictService; import org.apache.commons.collections4.CollectionUtils; @@ -80,6 +81,8 @@ public class IssueProjectCategoryDictServiceImpl extends BaseServiceImpl page(Map params) { @@ -269,8 +272,8 @@ public class IssueProjectCategoryDictServiceImpl extends BaseServiceImpl%s,分类Id->%s", formDTO.getCustomerId(), formDTO.getCategoryId())); throw new RuntimeException("分类、标签信息修改失败!"); } - //4.修改缓存中标签状态 todo - + //4.修改缓存中标签状态 + dictRedis.updateTagAvailabilityBySecondCategoryIds(formDTO.getCustomerId(),formDTO.getSecondCategorylist(),formDTO.getType()); } /** diff --git a/epmet-module/gov-issue/gov-issue-server/src/main/resources/mapper/IssueProjectTagDictDao.xml b/epmet-module/gov-issue/gov-issue-server/src/main/resources/mapper/IssueProjectTagDictDao.xml index e141bba4b1..487dd5b466 100644 --- a/epmet-module/gov-issue/gov-issue-server/src/main/resources/mapper/IssueProjectTagDictDao.xml +++ b/epmet-module/gov-issue/gov-issue-server/src/main/resources/mapper/IssueProjectTagDictDao.xml @@ -88,37 +88,87 @@ + + + + + +