Ver código fonte

公众号入口(type=0/1/4) 不再硬编码 channel_name,改按 ghName 反查 demand 表 channel_level3 → channel_name,自投公众号(125 个,channel='公众号投流-稳定')能正确命中本渠道 demand 池,不再被错路由到合作-即转/Daily 后退化到大盘。企微(type=2/3)/小程序(type=5) 保持 type 直推。新增 MapperExt selectChannelNameByGh(dt, ghName);删除 3 处 ghName 退化兜底(fetchPriorScene/fetchPriorDimension/fetchPosterior),边缘 gh 失数据时直接进跨渠道退化。无 DDL/无缓存,每次实时反查,单次 SQL 30~660ms。

刘立冬 9 horas atrás
pai
commit
9cd30f10d4

+ 7 - 0
api-module/src/main/java/com/tzld/piaoquan/api/dao/mapper/contentplatform/ext/ContentPlatformDemandVideoMapperExt.java

@@ -31,6 +31,13 @@ public interface ContentPlatformDemandVideoMapperExt {
 
     String getMaxDt(@Param("channelName") String channelName);
 
+    /**
+     * 按 ghName(channel_level3) 反查所属 channel_name。
+     * 业务约定一个公众号只归属一个 channel,故 LIMIT 1。
+     * 未命中返回 null,由调用方决定回退。
+     */
+    String selectChannelNameByGh(@Param("dt") String dt, @Param("ghName") String ghName);
+
     /**
      * 推荐场景候选池查询:按 demand_strategy 取指定 crowd_segment 的候选行,
      * 按 total_rov DESC, score DESC 排,最多取 limit 行。

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

@@ -643,10 +643,7 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
      * cdjh 优质相似 0514 验证保留 ~54%,量大有意义;
      * priorScene 池基数小(单 channel 几十~百条),仍保持 >0(在 groupAndTopK 内兜底)。 */
     private static final double DEMAND_MIN_ROV = 0.02;
-    /** type → channel_name 映射(强过滤):同 crowd_segment 跨渠道客户(如 gzyhc/wxm)按入口平台切数据源 */
-    private static final String CHANNEL_NAME_GZH = "公众号合作-即转-稳定";
-    /** 服务号推送 / 公众号推送 走 Daily 人群_渠道,与即转稳定数据隔离 */
-    private static final String CHANNEL_NAME_GZH_DAILY = "公众号合作-Daily-自选";
+    /** channel_name 映射:企微/小程序 type 直推,公众号入口按 ghName 反查 demand 表(见 resolveChannelName)。 */
     private static final String CHANNEL_NAME_QW  = "群/企微合作-稳定";
     private static final String CHANNEL_NAME_XCX = "小程序投流-稳定";
     private static final double PRIOR_GROUP_KEEP_RATIO = 0.5;
@@ -660,21 +657,27 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
     /**
      * 推导 channel_name(人群_渠道) 作为 demand 池强过滤。
      * 信号优先级:
-     *   1. type 明确时按 type 映射 — 0→公众号合作-即转-稳定;1/4→公众号合作-Daily-自选;2/3→群/企微合作-稳定;5→小程序投流-稳定
-     *   2. type=999/null 但带 ghName(公众号参数)→ 公众号入口,映射即转稳定(与历史一致)
-     *   3. 否则 null,不限 channel_name(保留原行为)
-     * type 取值: 0-自动回复(公众号入口) / 1-服务号推送 / 2-企微-社群 / 3-企微-自动回复 / 4-公众号推送 / 5-小程序投流 / 999-不限。
-     * 作用:解决 crowd_segment 跨渠道客户(如 gzyhc/wxm)在企微/公众号入口下被对侧数据污染的问题。
+     *   1. 企微入口(type=2/3) → 群/企微合作-稳定
+     *   2. 小程序投流(type=5) → 小程序投流-稳定
+     *   3. 公众号入口(type=0/1/4)或仅传 ghName:按 ghName 反查 demand 表 channel_level3 → channel_name
+     *      ─ 业务约定一个公众号只归属一个 channel(合作-即转 / 合作-Daily-自选 / 投流-稳定 三选一),
+     *        反查失败(新账号或上游当天没产)返回 null,不限 channel_name(保留兜底行为)。
+     *   4. 否则 null,不限 channel_name。
+     * 反查每次实时查表(已规避索引/缓存改造),首次请求 30~660ms,后续受 InnoDB buffer pool 缓存。
      */
     private String resolveChannelName(VideoContentListParam param) {
         Integer type = param.getType();
         if (type != null) {
             if (type == 2 || type == 3) return CHANNEL_NAME_QW;
-            if (type == 1 || type == 4) return CHANNEL_NAME_GZH_DAILY;
-            if (type == 0) return CHANNEL_NAME_GZH;
             if (type == 5) return CHANNEL_NAME_XCX;
         }
-        if (StringUtils.hasText(param.getGhName())) return CHANNEL_NAME_GZH;
+        String ghName = param.getGhName();
+        if (StringUtils.hasText(ghName)) {
+            String dt = demandVideoMapperExt.getMaxDt(null);
+            if (StringUtils.hasText(dt)) {
+                return demandVideoMapperExt.selectChannelNameByGh(dt, ghName);
+            }
+        }
         return null;
     }
 
@@ -988,10 +991,6 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
         // priorScene 池新识别:demand_strategy='人群需求' AND match_method='场景已看视频'(0519+ 起,旧 demand_strategy='人群需求-场景' 已迁走)
         List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
                 dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, null, null, null, ghName, null, category, MATCH_METHOD_PRIOR_SCENE, crowdPackage, limit, false);
-        if (ghName != null && rows.isEmpty()) {
-            rows = demandVideoMapperExt.selectForRecommend(
-                    dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR_SCENE, crowdPackage, limit, false);
-        }
         // 跨渠道退化:channel_name 命中但 crowd_segment 在对侧渠道下 0 行(如公众号账号切到企微入口)→ 去 crowd_segment,只按 channel_name 拉通用数据
         if (channelName != null && rows.isEmpty()) {
             rows = demandVideoMapperExt.selectForRecommend(
@@ -1062,10 +1061,6 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
         List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
                 dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, dimension, null, null, ghName, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, false);
 
-        if (ghName != null && rows.isEmpty()) {
-            rows = demandVideoMapperExt.selectForRecommend(
-                    dt, channelName, crowdSegment, DEMAND_STRATEGY_PRIOR, dimension, null, null, null, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, false);
-        }
         if (channelName != null && rows.isEmpty()) {
             rows = demandVideoMapperExt.selectForRecommend(
                     dt, channelName, null, DEMAND_STRATEGY_PRIOR, dimension, null, null, null, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, false);
@@ -1143,11 +1138,6 @@ public class ContentPlatformPlanServiceImpl implements ContentPlatformPlanServic
         List<ContentPlatformDemandVideo> rows = demandVideoMapperExt.selectForRecommend(
                 dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, null, ghName, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, true);
 
-        // 退化:该 ghName 无数据 → 退回渠道粒度
-        if (ghName != null && rows.isEmpty()) {
-            rows = demandVideoMapperExt.selectForRecommend(
-                    dt, channelName, crowdSegment, DEMAND_STRATEGY_POSTERIOR, null, null, null, null, null, category, MATCH_METHOD_PRIOR, crowdPackage, fetchLimit, true);
-        }
         // 跨渠道退化:channel_name 命中但 crowd_segment 在对侧 0 行 → 去 crowd_segment 拉通用数据
         if (channelName != null && rows.isEmpty()) {
             rows = demandVideoMapperExt.selectForRecommend(

+ 9 - 0
api-module/src/main/resources/mapper/contentplatform/ext/ContentPlatformDemandVideoMapperExt.xml

@@ -90,6 +90,15 @@
         </if>
     </select>
 
+    <select id="selectChannelNameByGh" resultType="java.lang.String">
+        SELECT channel_name
+        FROM content_platform_demand_video
+        WHERE dt = #{dt}
+          AND channel_level3 = #{ghName}
+          AND status = 1
+        LIMIT 1
+    </select>
+
     <select id="selectForRecommend" resultType="com.tzld.piaoquan.api.model.po.contentplatform.ContentPlatformDemandVideo">
         SELECT id, dt, channel_name, channel_level3, crowd_segment, dimension, point_type, standard_element,
                category_name, category, demand_id, crowd_package, conversion_target, partner, account, scene_value,