Преглед на файлове

优化AI返回的店铺列表接口

liudongzhi преди 1 месец
родител
ревизия
5e3d002f42
променени са 1 файла, в които са добавени 76 реда и са изтрити 43 реда
  1. 76 43
      alien-store/src/main/java/shop/alien/store/controller/AiSearchController.java

+ 76 - 43
alien-store/src/main/java/shop/alien/store/controller/AiSearchController.java

@@ -24,14 +24,22 @@ import shop.alien.entity.store.LifeBlacklist;
 import shop.alien.entity.store.StoreImg;
 import shop.alien.entity.store.StoreUser;
 import shop.alien.entity.store.vo.StoreInfoVo;
+import shop.alien.entity.store.CommonRating;
+import shop.alien.mapper.CommonRatingMapper;
 import shop.alien.mapper.LifeBlacklistMapper;
 import shop.alien.mapper.StoreImgMapper;
 import shop.alien.mapper.StoreUserMapper;
 import shop.alien.store.annotation.TrackEvent;
 import shop.alien.store.service.CommonRatingService;
 import shop.alien.store.service.StoreImgService;
+import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
 
+import java.time.Instant;
+import java.time.ZoneId;
+import java.time.format.DateTimeFormatter;
 import java.util.*;
+import java.util.concurrent.CompletableFuture;
+import java.util.concurrent.Executor;
 import java.util.stream.Collectors;
 
 
@@ -56,6 +64,7 @@ public class AiSearchController {
     private final RestTemplate restTemplate;
     private final StoreImgService storeImgService;
     private final CommonRatingService commonRatingService;
+    private final CommonRatingMapper commonRatingMapper;
 
     private final LifeBlacklistMapper lifeBlacklistMapper;
 
@@ -135,19 +144,22 @@ public class AiSearchController {
 
         HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, null);
         try {
+            DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSS").withZone(ZoneId.systemDefault());
+            log.info("调用AI模糊搜索接口 请求参数------{} 时间: {}", requestBody, formatter.format(Instant.now()));
             ResponseEntity<String> stringResponseEntity = restTemplate.postForEntity(aiSearchFuzzyUrl, request, String.class);
             String body = stringResponseEntity.getBody();
-            log.info("调用AI列表接口 处理前v 接口返回------{}", body);
+            log.info("调用AI列表接口 处理前v 接口返回------{}  时间: {}", body, formatter.format(Instant.now()));
             JSONObject jsonObject = JSONObject.parseObject(body);
             JSONObject jsonObject1 = new JSONObject();
             // 模糊搜索:从related_results和matched_results字段获取数据
             List<StoreInfoVo> result = convertToStoreInfoList(jsonObject.getJSONArray("results"),map.get("userId"));
 
-            // 查找图片并设置到result中(图片类型1-入口图)
-            fillStoreImages(result, 1);
-
-            // 填充评论总数
-            fillRatingCount(result);
+            // 并发处理图片和评论数据,提升性能
+            CompletableFuture<Void> imageFuture = CompletableFuture.runAsync(() -> fillStoreImages(result, 1));
+            CompletableFuture<Void> ratingFuture = CompletableFuture.runAsync(() -> fillRatingCountBatch(result));
+            
+            // 等待两个任务完成
+            CompletableFuture.allOf(imageFuture, ratingFuture).join();
 
             jsonObject1.put("records", result);
 
@@ -203,24 +215,7 @@ public class AiSearchController {
                 if(collect.contains(storeInfo.getId())){
                     continue;
                 }
-                Integer totalCount = 0;
-                double storeScore;
-                Object ratingObj =  commonRatingService.getRatingCount(storeInfo.getId(), 1);
-                if (ratingObj != null) {
-                    Map<String, Object> ratingMap = (Map<String, Object>) ratingObj;
-                    Object totalCountObj = ratingMap.get("totalCount");
-                    if (totalCountObj != null) {
-                        // 安全转换为整数
-                        try {
-                            totalCount = Integer.parseInt(totalCountObj.toString().trim());
-                        } catch (NumberFormatException e) {
-                            totalCount = 0; // 转换失败时默认值
-                        }
-                    } else {
-                        totalCount = 0;
-                    }
-                }
-                storeInfo.setTotalNum(totalCount.toString());
+                // 移除这里的getRatingCount调用,统一在fillRatingCountBatch中批量处理
                 storeInfoList.add(storeInfo);
             }
         }
@@ -282,34 +277,72 @@ public class AiSearchController {
     }
 
     /**
-     * 填充评论总数到StoreInfoVo列表中
+     * 填充评论总数到StoreInfoVo列表中(批量查询优化版本)
+     * 使用批量查询替代N+1查询,大幅提升性能
      *
      * @param result StoreInfoVo列表
      */
-    private void fillRatingCount(List<StoreInfoVo> result) {
+    private void fillRatingCountBatch(List<StoreInfoVo> result) {
         if (result == null || result.isEmpty()) {
             return;
         }
 
-        for (StoreInfoVo storeInfo : result) {
-            if (storeInfo.getId() != null) {
-                try {
-                    // 调用评论服务获取评论总数,businessId传id,businessType传1
-                    Object ratingCountObj = commonRatingService.getRatingCount(storeInfo.getId(), 1);
-
-                    // 将返回的Object转换为Map
-                    if (ratingCountObj instanceof Map) {
-                        Map<String, Object> ratingCountMap = (Map<String, Object>) ratingCountObj;
-                        // 从map中取出totalCount字段
-                        Object totalCount = ratingCountMap.get("totalCount");
-                        if (totalCount != null) {
-                            // 赋值给totalNum字段(转为String类型)
-                            storeInfo.setTotalNum(String.valueOf(totalCount));
+        // 提取所有storeId
+        List<Integer> storeIdList = result.stream()
+                .map(StoreInfoVo::getId)
+                .filter(id -> id != null)
+                .distinct()
+                .collect(Collectors.toList());
+
+        if (storeIdList.isEmpty()) {
+            return;
+        }
+
+        try {
+            // 批量查询所有store的评价记录(只查询审核通过且展示的)
+            LambdaQueryWrapper<CommonRating> wrapper = new LambdaQueryWrapper<>();
+            wrapper.in(CommonRating::getBusinessId, storeIdList)
+                    .eq(CommonRating::getBusinessType, 1)
+                    .eq(CommonRating::getAuditStatus, 1)
+                    .eq(CommonRating::getIsShow, 1);
+            List<CommonRating> allRatings = commonRatingMapper.selectList(wrapper);
+
+            // 按businessId分组统计评论总数
+            Map<Integer, Long> ratingCountMap = allRatings.stream()
+                    .collect(Collectors.groupingBy(
+                            CommonRating::getBusinessId,
+                            Collectors.counting()
+                    ));
+
+            // 设置评论总数到对应的StoreInfoVo
+            for (StoreInfoVo storeInfo : result) {
+                if (storeInfo.getId() != null) {
+                    Long count = ratingCountMap.get(storeInfo.getId());
+                    storeInfo.setTotalNum(count != null ? String.valueOf(count) : "0");
+                }
+            }
+        } catch (Exception e) {
+            log.error("批量获取评论总数失败", e);
+            // 如果批量查询失败,回退到单个查询(兜底策略)
+            for (StoreInfoVo storeInfo : result) {
+                if (storeInfo.getId() != null) {
+                    try {
+                        Object ratingCountObj = commonRatingService.getRatingCount(storeInfo.getId(), 1);
+                        if (ratingCountObj instanceof Map) {
+                            Map<String, Object> ratingCountMap = (Map<String, Object>) ratingCountObj;
+                            Object totalCount = ratingCountMap.get("totalCount");
+                            if (totalCount != null) {
+                                storeInfo.setTotalNum(String.valueOf(totalCount));
+                            } else {
+                                storeInfo.setTotalNum("0");
+                            }
+                        } else {
+                            storeInfo.setTotalNum("0");
                         }
+                    } catch (Exception ex) {
+                        log.warn("获取评论总数失败,storeId: {}", storeInfo.getId(), ex);
+                        storeInfo.setTotalNum("0");
                     }
-                } catch (Exception e) {
-                    log.warn("获取评论总数失败,storeId: {}", storeInfo.getId(), e);
-                    // 如果获取失败,继续处理下一个,不影响其他数据
                 }
             }
         }