Prechádzať zdrojové kódy

Merge branch 'cooperation_video_candidate_pool_improved_lld_0509' into test

demand 池跨渠道 crowd_segment 兜底退化
刘立冬 6 dní pred
rodič
commit
accf0b61f1

+ 17 - 0
api-module/src/main/java/com/tzld/piaoquan/api/service/contentplatform/impl/ContentPlatformPlanServiceImpl.java

@@ -870,6 +870,11 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
             rows = demandVideoMapperExt.selectForRecommend(
                     dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR_SCENE, null, null, null, null, null, limit, false);
         }
+        // 跨渠道退化:channel_name 命中但 crowd_segment 在对侧渠道下 0 行(如公众号账号切到企微入口)→ 去 crowd_segment,只按 channel_name 拉通用数据
+        if (channelName != null && rows.isEmpty()) {
+            rows = demandVideoMapperExt.selectForRecommend(
+                    dt, channelName, null, DEMAND_STRATEGY_PRIOR_SCENE, null, null, null, null, null, limit, false);
+        }
         // 1. 同 video_id 取 total_rov 最大的代表行(SQL 已排序,putIfAbsent 保留首次)
         LinkedHashMap<Long, ContentPlatformDemandVideo> bestPerVideo = new LinkedHashMap<>();
         for (ContentPlatformDemandVideo r : rows) {
@@ -921,6 +926,11 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
             rows = demandVideoMapperExt.selectForRecommend(
                     dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, PRIOR_PREMIUM_DIMENSION, null, null, null, null, fetchLimit, false);
         }
+        // 跨渠道退化:channel_name 命中但 crowd_segment 在对侧 0 行 → 去 crowd_segment 拉通用数据
+        if (channelName != null && rows.isEmpty()) {
+            rows = demandVideoMapperExt.selectForRecommend(
+                    dt, channelName, null, DEMAND_STRATEGY_PRIOR, PRIOR_PREMIUM_DIMENSION, null, null, null, null, fetchLimit, false);
+        }
 
         Function<ContentPlatformDemandVideo, String> keyFn = r ->
                 (r.getPointType() == null ? "" : r.getPointType()) + "\u0001"
@@ -994,6 +1004,13 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
             stageRel = demandVideoMapperExt.selectForRecommend(
                     dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_REL_LIKE, null, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
         }
+        // 跨渠道退化:channel_name 命中但 crowd_segment 在对侧 0 行 → 去 crowd_segment 拉通用数据
+        if (channelName != null && stageAbs.isEmpty() && stageRel.isEmpty()) {
+            stageAbs = demandVideoMapperExt.selectForRecommend(
+                    dt, channelName, null, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_ABS_LIKE, null, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
+            stageRel = demandVideoMapperExt.selectForRecommend(
+                    dt, channelName, null, DEMAND_STRATEGY_POSTERIOR, null, null, POSTERIOR_FILTER_REL_LIKE, null, POSTERIOR_DRIVE_DIMENSION_TIME, fetchLimit, true);
+        }
 
         Function<ContentPlatformDemandVideo, String> keyFn = r ->
                 r.getDemandContentId() == null ? "" : r.getDemandContentId();

+ 6 - 3
docs/recommend-ordering.md

@@ -77,7 +77,10 @@ ORDER BY total_rov DESC, score DESC
 LIMIT 10000
 ```
 
-退化:如果 `ghName` 非空但查 0 条,**去掉 `ghName` 再查一次**(拿全渠道兜底)。`channel_name` 在退化时**保留**(强过滤,跨渠道污染必须先挡掉)。
+退化阶梯(细→粗):
+1. `ghName` 非空但查 0 条 → **去掉 `ghName` 再查一次**(拿全 channel 兜底)
+2. 仍为 0 且 `channel_name` 非空 → **再去掉 `crowd_segment`**,只按 `channel_name` 拉(跨渠道兜底,如公众号账号切到企微入口)
+3. `channel_name` 在所有退化层**始终保留**(强过滤,跨渠道污染必须先挡掉)
 
 后处理(顺序):
 1. 同 `videoId` 去重,保留首次出现(SQL 已按 `total_rov DESC, score DESC` 排序 → 首次 = 该视频的"最强代表需求"行)
@@ -102,7 +105,7 @@ SELECT ... WHERE ... AND channel_name=:resolvedChannelName(可空)
 ORDER BY total_rov DESC, score DESC LIMIT 30000
 ```
 
-退化:查询为空且 `ghName` 非空 → 去 `ghName` 重查(`channel_name` 仍保留)
+退化阶梯:`ghName` 非空且 0 条 → 去 `ghName` 重查;仍 0 且 `channel_name` 非空 → 再去 `crowd_segment` 重查(跨渠道兜底)。`channel_name` 始终保留
 
 **[新] 特征组分位裁剪 (`retainTopGroupsByTotalRov`,`keepRatio=0.5`)**:
 - 按 `(point_type, standard_element)` 分组,取每组 `max(total_rov)`(即该特征的人群需求强度)
@@ -143,7 +146,7 @@ ORDER BY total_rov DESC, score DESC LIMIT 30000
 SELECT ... AND demand_filter_sort_strategy LIKE '相对裂变率%' AND drive_dimension_time='昨日' ...
 ```
 
-退化A、B 都空且 `ghName` 非空 → 去 `ghName` 重查(`drive_dimension_time='昨日'` 与 `channel_name` 强过滤仍保留)
+退化阶梯:A、B 都空且 `ghName` 非空 → 去 `ghName` 重查;A、B 仍都空且 `channel_name` 非空 → 再去 `crowd_segment` 重查(跨渠道兜底)。`drive_dimension_time='昨日'` 与 `channel_name` 强过滤始终保留
 
 每段进 `groupAndTopK`:
 - 分组键:`demand_content_id`