|
@@ -7,6 +7,9 @@ import com.ctrip.framework.apollo.spring.annotation.ApolloJsonValue;
|
|
|
import com.google.common.collect.Lists;
|
|
import com.google.common.collect.Lists;
|
|
|
import com.tzld.videoVector.api.LibraryApiService;
|
|
import com.tzld.videoVector.api.LibraryApiService;
|
|
|
import com.tzld.videoVector.common.constant.VectorConstants;
|
|
import com.tzld.videoVector.common.constant.VectorConstants;
|
|
|
|
|
+import com.tzld.videoVector.common.enums.DimensionEnum;
|
|
|
|
|
+import com.tzld.videoVector.common.enums.MatchMethodEnum;
|
|
|
|
|
+import com.tzld.videoVector.common.enums.PointTypeEnum;
|
|
|
import com.tzld.videoVector.dao.mapper.pgVector.ChannelDemandMatchConfigMapper;
|
|
import com.tzld.videoVector.dao.mapper.pgVector.ChannelDemandMatchConfigMapper;
|
|
|
import com.tzld.videoVector.dao.mapper.pgVector.ChannelDemandMatchResultMapper;
|
|
import com.tzld.videoVector.dao.mapper.pgVector.ChannelDemandMatchResultMapper;
|
|
|
import com.tzld.videoVector.dao.mapper.pgVector.ext.ChannelDemandMatchResultMapperExt;
|
|
import com.tzld.videoVector.dao.mapper.pgVector.ext.ChannelDemandMatchResultMapperExt;
|
|
@@ -68,47 +71,12 @@ public class ChannelDemandMatchJob {
|
|
|
@Resource
|
|
@Resource
|
|
|
private LibraryApiService libraryApiService;
|
|
private LibraryApiService libraryApiService;
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 召回结果Redis缓存前缀
|
|
|
|
|
- */
|
|
|
|
|
- private static final String RECALL_CACHE_PREFIX = "channel_demand:recall:";
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * Library API 召回结果Redis缓存前缀
|
|
|
|
|
- */
|
|
|
|
|
- private static final String LIBRARY_RECALL_CACHE_PREFIX = "channel_demand:library_recall:";
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 召回结果缓存过期时间(秒)
|
|
|
|
|
- */
|
|
|
|
|
- private static final long RECALL_CACHE_EXPIRE = 6 * 60 * 60;
|
|
|
|
|
-
|
|
|
|
|
/**
|
|
/**
|
|
|
* 需求匹配并发线程数(单个维度批次内的需求匹配)
|
|
* 需求匹配并发线程数(单个维度批次内的需求匹配)
|
|
|
*/
|
|
*/
|
|
|
@Value("${channel.demand.match.thread-pool-size:50}")
|
|
@Value("${channel.demand.match.thread-pool-size:50}")
|
|
|
private int matchThreadPoolSize;
|
|
private int matchThreadPoolSize;
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 匹配手段:场景已看视频(来自维度统计表,不走向量召回)
|
|
|
|
|
- */
|
|
|
|
|
- private static final String MATCH_METHOD_DIMENSION_STAT = "场景已看视频";
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 匹配手段:视频库_解构特征_向量相似匹配(走向量召回)
|
|
|
|
|
- */
|
|
|
|
|
- private static final String MATCH_METHOD_RECOMMEND_LIB = "视频库_解构特征_向量相似匹配";
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 匹配手段:视频库_解构特征点_精准匹配(Library API 精准匹配)
|
|
|
|
|
- */
|
|
|
|
|
- private static final String MATCH_METHOD_RECOMMEND_LIB_EXACT = "视频库_解构特征点_精准匹配";
|
|
|
|
|
-
|
|
|
|
|
- /**
|
|
|
|
|
- * 需求来源:优质相似(对应 demand_strategy 取值)
|
|
|
|
|
- */
|
|
|
|
|
- private static final String DEMAND_SOURCE_QUALITY_SIM = "优质相似";
|
|
|
|
|
-
|
|
|
|
|
// ============== 匹配结果默认值(固定文案) ==============
|
|
// ============== 匹配结果默认值(固定文案) ==============
|
|
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -208,17 +176,6 @@ public class ChannelDemandMatchJob {
|
|
|
@Value("${video.detail.metrics.days:7}")
|
|
@Value("${video.detail.metrics.days:7}")
|
|
|
private int metricsDays;
|
|
private int metricsDays;
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 点类型 → 向量配置编码映射
|
|
|
|
|
- */
|
|
|
|
|
- private static final Map<String, List<String>> POINT_TYPE_CONFIG_CODE_MAP = new HashMap<>();
|
|
|
|
|
-
|
|
|
|
|
- static {
|
|
|
|
|
- POINT_TYPE_CONFIG_CODE_MAP.put("关键点", Arrays.asList("VIDEO_KEYPOINT", "KEYPOINT_SUBSTANCE", "KEYPOINT_FORM"));
|
|
|
|
|
- POINT_TYPE_CONFIG_CODE_MAP.put("灵感点", Arrays.asList("VIDEO_INSPIRATION", "INSPIRATION_SUBSTANCE", "INSPIRATION_FORM"));
|
|
|
|
|
- POINT_TYPE_CONFIG_CODE_MAP.put("目的点", Arrays.asList("VIDEO_PURPOSE", "PURPOSE_SUBSTANCE", "PURPOSE_FORM"));
|
|
|
|
|
- }
|
|
|
|
|
-
|
|
|
|
|
@PostConstruct
|
|
@PostConstruct
|
|
|
public void initConfigExecutor() {
|
|
public void initConfigExecutor() {
|
|
|
this.configExecutor = new ThreadPoolExecutor(
|
|
this.configExecutor = new ThreadPoolExecutor(
|
|
@@ -354,7 +311,7 @@ public class ChannelDemandMatchJob {
|
|
|
deleteExistingResults(config.getId(), dt);
|
|
deleteExistingResults(config.getId(), dt);
|
|
|
|
|
|
|
|
// 如果匹配手段为"场景已看视频",走独立的处理逻辑(不需要向量召回)
|
|
// 如果匹配手段为"场景已看视频",走独立的处理逻辑(不需要向量召回)
|
|
|
- if (MATCH_METHOD_DIMENSION_STAT.equals(config.getMatchMethod())) {
|
|
|
|
|
|
|
+ if (MatchMethodEnum.DIMENSION_STAT.getValue().equals(config.getMatchMethod())) {
|
|
|
processDimensionStatSource(config, dt, totalDemands, totalMatched, totalFailed);
|
|
processDimensionStatSource(config, dt, totalDemands, totalMatched, totalFailed);
|
|
|
return;
|
|
return;
|
|
|
}
|
|
}
|
|
@@ -474,6 +431,63 @@ public class ChannelDemandMatchJob {
|
|
|
return result;
|
|
return result;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 对"传播的分发"/"增长的分发"维度按渠道类分组取TopN%
|
|
|
|
|
+ * 与filterTopRovByGroup的区别:分组键为渠道类+维度(不含crowdSegment和channelLevel3)
|
|
|
|
|
+ *
|
|
|
|
|
+ * @param demands 待过滤的需求列表
|
|
|
|
|
+ * @param channelName 渠道名称,用于匹配Apollo配置
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<ChannelDemandMatchResult> filterTopRovByChannelForDistDimension(
|
|
|
|
|
+ List<ChannelDemandMatchResult> demands, String channelName) {
|
|
|
|
|
+ if (CollectionUtils.isEmpty(demands)) {
|
|
|
|
|
+ return Collections.emptyList();
|
|
|
|
|
+ }
|
|
|
|
|
+ // 获取该渠道的维度→比例配置
|
|
|
|
|
+ Map<String, Double> channelFilterConfig = topRovFilterConfig != null
|
|
|
|
|
+ ? topRovFilterConfig.getOrDefault(channelName, Collections.emptyMap())
|
|
|
|
|
+ : Collections.emptyMap();
|
|
|
|
|
+
|
|
|
|
|
+ if (channelFilterConfig.isEmpty()) {
|
|
|
|
|
+ return new ArrayList<>(demands);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<ChannelDemandMatchResult> toFilter = new ArrayList<>();
|
|
|
|
|
+ List<ChannelDemandMatchResult> keepAsIs = new ArrayList<>();
|
|
|
|
|
+ for (ChannelDemandMatchResult d : demands) {
|
|
|
|
|
+ if (channelFilterConfig.containsKey(d.getDimension())) {
|
|
|
|
|
+ toFilter.add(d);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ keepAsIs.add(d);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<ChannelDemandMatchResult> result = new ArrayList<>(keepAsIs);
|
|
|
|
|
+
|
|
|
|
|
+ if (toFilter.isEmpty()) {
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 按渠道类+维度分组(渠道类用于兼容多渠道场景,维度用于区分不同配置比例)
|
|
|
|
|
+ Map<String, List<ChannelDemandMatchResult>> grouped = toFilter.stream()
|
|
|
|
|
+ .collect(Collectors.groupingBy(d ->
|
|
|
|
|
+ nullToEmpty(d.getChannelName()) + "|"
|
|
|
|
|
+ + nullToEmpty(d.getDimension())));
|
|
|
|
|
+ for (List<ChannelDemandMatchResult> group : grouped.values()) {
|
|
|
|
|
+ group.sort((a, b) -> {
|
|
|
|
|
+ double rovA = a.getTotalRov() != null ? a.getTotalRov() : 0.0;
|
|
|
|
|
+ double rovB = b.getTotalRov() != null ? b.getTotalRov() : 0.0;
|
|
|
|
|
+ return Double.compare(rovB, rovA);
|
|
|
|
|
+ });
|
|
|
|
|
+ // 从分组中取任一元素的dimension获取配置比例
|
|
|
|
|
+ String dim = group.get(0).getDimension();
|
|
|
|
|
+ double ratio = channelFilterConfig.getOrDefault(dim, 0.25);
|
|
|
|
|
+ int topCount = Math.max(5, (int) Math.ceil(group.size() * ratio));
|
|
|
|
|
+ result.addAll(group.subList(0, Math.min(topCount, group.size())));
|
|
|
|
|
+ }
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
/**
|
|
/**
|
|
|
* 解析ODPS单条需求记录
|
|
* 解析ODPS单条需求记录
|
|
|
*/
|
|
*/
|
|
@@ -521,8 +535,8 @@ public class ChannelDemandMatchJob {
|
|
|
result.setMatchStatus((short) 0); // 待匹配
|
|
result.setMatchStatus((short) 0); // 待匹配
|
|
|
|
|
|
|
|
// 向量召回路径:匹配手段固定为视频库_解构特征_向量相似匹配;筛选/排序默认值按需求来源选择
|
|
// 向量召回路径:匹配手段固定为视频库_解构特征_向量相似匹配;筛选/排序默认值按需求来源选择
|
|
|
- result.setMatchMethod(MATCH_METHOD_RECOMMEND_LIB);
|
|
|
|
|
- if (DEMAND_SOURCE_QUALITY_SIM.equals(result.getDemandStrategy())) {
|
|
|
|
|
|
|
+ result.setMatchMethod(MatchMethodEnum.RECOMMEND_LIB.getValue());
|
|
|
|
|
+ if ("优质相似".equals(result.getDemandStrategy())) {
|
|
|
result.setMatchVideoFilter(VIDEO_FILTER_QUALITY_SIM_RECOMMEND);
|
|
result.setMatchVideoFilter(VIDEO_FILTER_QUALITY_SIM_RECOMMEND);
|
|
|
result.setMatchSort(SORT_QUALITY_SIM_RECOMMEND);
|
|
result.setMatchSort(SORT_QUALITY_SIM_RECOMMEND);
|
|
|
} else {
|
|
} else {
|
|
@@ -557,7 +571,7 @@ public class ChannelDemandMatchJob {
|
|
|
|
|
|
|
|
// 策略三:需求特征点类型+需求特征点 均有值 → 用需求特征点召回
|
|
// 策略三:需求特征点类型+需求特征点 均有值 → 用需求特征点召回
|
|
|
if ("特征点".equals(demand.getDemandType()) && hasValidValue(demand.getPointType()) && hasValidValue(demand.getStandardElement())) {
|
|
if ("特征点".equals(demand.getDemandType()) && hasValidValue(demand.getPointType()) && hasValidValue(demand.getStandardElement())) {
|
|
|
- List<String> configCodes = POINT_TYPE_CONFIG_CODE_MAP.getOrDefault(demand.getPointType(), Arrays.asList("VIDEO_TOPIC"));
|
|
|
|
|
|
|
+ List<String> configCodes = PointTypeEnum.getConfigCodesByValue(demand.getPointType());
|
|
|
List<ChannelDemandMatchResult> rows = new ArrayList<>();
|
|
List<ChannelDemandMatchResult> rows = new ArrayList<>();
|
|
|
for (String configCode : configCodes) {
|
|
for (String configCode : configCodes) {
|
|
|
rows.addAll(doRecall(demand, demand.getStandardElement(), configCode, topN / configCodes.size()));
|
|
rows.addAll(doRecall(demand, demand.getStandardElement(), configCode, topN / configCodes.size()));
|
|
@@ -572,7 +586,7 @@ public class ChannelDemandMatchJob {
|
|
|
List<ChannelDemandMatchResult> rows = doLibraryRecall(demand, topN);
|
|
List<ChannelDemandMatchResult> rows = doLibraryRecall(demand, topN);
|
|
|
allBatchRows.addAll(rows);
|
|
allBatchRows.addAll(rows);
|
|
|
// 向量匹配
|
|
// 向量匹配
|
|
|
- List<String> configCodes = POINT_TYPE_CONFIG_CODE_MAP.getOrDefault(demand.getMatchGeneralizedPointType(), Arrays.asList("VIDEO_TOPIC"));
|
|
|
|
|
|
|
+ List<String> configCodes = PointTypeEnum.getConfigCodesByValue(demand.getMatchGeneralizedPointType());
|
|
|
for (String configCode : configCodes) {
|
|
for (String configCode : configCodes) {
|
|
|
allBatchRows.addAll(doRecall(demand, demand.getMatchGeneralizedElement(), configCode, topN / configCodes.size()));
|
|
allBatchRows.addAll(doRecall(demand, demand.getMatchGeneralizedElement(), configCode, topN / configCodes.size()));
|
|
|
}
|
|
}
|
|
@@ -651,7 +665,7 @@ public class ChannelDemandMatchJob {
|
|
|
*/
|
|
*/
|
|
|
private List<ChannelDemandMatchResult> doLibraryRecall(ChannelDemandMatchResult demand, int topN) {
|
|
private List<ChannelDemandMatchResult> doLibraryRecall(ChannelDemandMatchResult demand, int topN) {
|
|
|
String elementName = demand.getMatchGeneralizedElement();
|
|
String elementName = demand.getMatchGeneralizedElement();
|
|
|
- String cacheKey = LIBRARY_RECALL_CACHE_PREFIX + Md5Util.encoderByMd5(elementName);
|
|
|
|
|
|
|
+ String cacheKey = VectorConstants.CHANNEL_DEMAND_LIBRARY_RECALL_CACHE_PREFIX + Md5Util.encoderByMd5(elementName);
|
|
|
|
|
|
|
|
// 1. 尝试从缓存读取
|
|
// 1. 尝试从缓存读取
|
|
|
List<CachedPost> cachedPosts = loadLibraryRecallCache(cacheKey);
|
|
List<CachedPost> cachedPosts = loadLibraryRecallCache(cacheKey);
|
|
@@ -750,7 +764,7 @@ public class ChannelDemandMatchJob {
|
|
|
|
|
|
|
|
// 7. 写入缓存
|
|
// 7. 写入缓存
|
|
|
try {
|
|
try {
|
|
|
- redisUtils.set(cacheKey, JSON.toJSONString(newCachedPosts), RECALL_CACHE_EXPIRE);
|
|
|
|
|
|
|
+ redisUtils.set(cacheKey, JSON.toJSONString(newCachedPosts), VectorConstants.CHANNEL_DEMAND_RECALL_CACHE_EXPIRE);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.warn("写入Library API召回缓存失败, key={}: {}", cacheKey, e.getMessage());
|
|
log.warn("写入Library API召回缓存失败, key={}: {}", cacheKey, e.getMessage());
|
|
|
}
|
|
}
|
|
@@ -790,7 +804,7 @@ public class ChannelDemandMatchJob {
|
|
|
Long postId = Long.parseLong(cp.getPostId());
|
|
Long postId = Long.parseLong(cp.getPostId());
|
|
|
|
|
|
|
|
ChannelDemandMatchResult row = copyDemandFields(demand);
|
|
ChannelDemandMatchResult row = copyDemandFields(demand);
|
|
|
- row.setMatchMethod(MATCH_METHOD_RECOMMEND_LIB_EXACT);
|
|
|
|
|
|
|
+ row.setMatchMethod(MatchMethodEnum.RECOMMEND_LIB_EXACT.getValue());
|
|
|
if (StringUtils.hasText(row.getDemandType())) {
|
|
if (StringUtils.hasText(row.getDemandType())) {
|
|
|
if ("特征点".equals(row.getDemandType())) {
|
|
if ("特征点".equals(row.getDemandType())) {
|
|
|
row.setDemandType("聚类特征点");
|
|
row.setDemandType("聚类特征点");
|
|
@@ -848,7 +862,7 @@ public class ChannelDemandMatchJob {
|
|
|
* 带Redis缓存的召回:相同queryText+configCode+topN直接复用缓存结果
|
|
* 带Redis缓存的召回:相同queryText+configCode+topN直接复用缓存结果
|
|
|
*/
|
|
*/
|
|
|
private RecallVideoScoreVO getRecallResultWithCache(RecallVideoScoreParam param) {
|
|
private RecallVideoScoreVO getRecallResultWithCache(RecallVideoScoreParam param) {
|
|
|
- String cacheKey = RECALL_CACHE_PREFIX + Md5Util.encoderByMd5(
|
|
|
|
|
|
|
+ String cacheKey = VectorConstants.CHANNEL_DEMAND_RECALL_CACHE_PREFIX + Md5Util.encoderByMd5(
|
|
|
param.getQueryText() + "|" + param.getConfigCode() + "|" + param.getTopN());
|
|
param.getQueryText() + "|" + param.getConfigCode() + "|" + param.getTopN());
|
|
|
try {
|
|
try {
|
|
|
String cached = redisUtils.get(cacheKey);
|
|
String cached = redisUtils.get(cacheKey);
|
|
@@ -863,7 +877,7 @@ public class ChannelDemandMatchJob {
|
|
|
|
|
|
|
|
if (scoreVO != null && !CollectionUtils.isEmpty(scoreVO.getItems())) {
|
|
if (scoreVO != null && !CollectionUtils.isEmpty(scoreVO.getItems())) {
|
|
|
try {
|
|
try {
|
|
|
- redisUtils.set(cacheKey, JSON.toJSONString(scoreVO), RECALL_CACHE_EXPIRE);
|
|
|
|
|
|
|
+ redisUtils.set(cacheKey, JSON.toJSONString(scoreVO), VectorConstants.CHANNEL_DEMAND_RECALL_CACHE_EXPIRE);
|
|
|
} catch (Exception e) {
|
|
} catch (Exception e) {
|
|
|
log.warn("写入召回缓存失败, key={}: {}", cacheKey, e.getMessage());
|
|
log.warn("写入召回缓存失败, key={}: {}", cacheKey, e.getMessage());
|
|
|
}
|
|
}
|
|
@@ -1011,7 +1025,7 @@ public class ChannelDemandMatchJob {
|
|
|
// 数据源差异由 config.match_method 区分;此处 demand_strategy 与配置保持一致(迁移后统一为"人群需求")
|
|
// 数据源差异由 config.match_method 区分;此处 demand_strategy 与配置保持一致(迁移后统一为"人群需求")
|
|
|
result.setDemandStrategy(config.getDemandStrategy());
|
|
result.setDemandStrategy(config.getDemandStrategy());
|
|
|
// 匹配手段/筛选/排序 固定默认值(场景已看视频)
|
|
// 匹配手段/筛选/排序 固定默认值(场景已看视频)
|
|
|
- result.setMatchMethod(MATCH_METHOD_DIMENSION_STAT);
|
|
|
|
|
|
|
+ result.setMatchMethod(MatchMethodEnum.DIMENSION_STAT.getValue());
|
|
|
result.setMatchVideoFilter(VIDEO_FILTER_DIMENSION_STAT);
|
|
result.setMatchVideoFilter(VIDEO_FILTER_DIMENSION_STAT);
|
|
|
result.setMatchSort(SORT_DIMENSION_STAT);
|
|
result.setMatchSort(SORT_DIMENSION_STAT);
|
|
|
|
|
|
|
@@ -1095,8 +1109,29 @@ public class ChannelDemandMatchJob {
|
|
|
// 按Apollo配置对增长的头部等维度执行分组TOP过滤
|
|
// 按Apollo配置对增长的头部等维度执行分组TOP过滤
|
|
|
String channelName = config.getChannelName();
|
|
String channelName = config.getChannelName();
|
|
|
int beforeFilterCount = results.size();
|
|
int beforeFilterCount = results.size();
|
|
|
- List<ChannelDemandMatchResult> filteredResults = filterTopRovByGroup(results, channelName);
|
|
|
|
|
- log.info("场景已看视频 渠道 {} 分组过滤后 {} -> {} 条", channelName, beforeFilterCount, filteredResults.size());
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 分离头部维度和分发维度:分发维度按渠道类分组过滤,头部维度保持原有逻辑
|
|
|
|
|
+ List<ChannelDemandMatchResult> headResults = new ArrayList<>();
|
|
|
|
|
+ List<ChannelDemandMatchResult> distResults = new ArrayList<>();
|
|
|
|
|
+ for (ChannelDemandMatchResult r : results) {
|
|
|
|
|
+ if (DimensionEnum.distributionValueSet().contains(r.getDimension())) {
|
|
|
|
|
+ distResults.add(r);
|
|
|
|
|
+ } else {
|
|
|
|
|
+ headResults.add(r);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 头部维度:保持现有逻辑(按 crowdSegment|channelLevel3|dimension 分组过滤)
|
|
|
|
|
+ List<ChannelDemandMatchResult> filteredHead = filterTopRovByGroup(headResults, channelName);
|
|
|
|
|
+ // 分发维度:按 渠道类 分组取前百分之几
|
|
|
|
|
+ List<ChannelDemandMatchResult> filteredDist = filterTopRovByChannelForDistDimension(distResults, channelName);
|
|
|
|
|
+
|
|
|
|
|
+ List<ChannelDemandMatchResult> filteredResults = new ArrayList<>();
|
|
|
|
|
+ filteredResults.addAll(filteredHead);
|
|
|
|
|
+ filteredResults.addAll(filteredDist);
|
|
|
|
|
+
|
|
|
|
|
+ log.info("场景已看视频 渠道 {} 分组过滤后 {} -> {} 条 (头部{}条, 分发{}条)",
|
|
|
|
|
+ channelName, beforeFilterCount, filteredResults.size(), filteredHead.size(), filteredDist.size());
|
|
|
|
|
|
|
|
// 批量写入
|
|
// 批量写入
|
|
|
for (List<ChannelDemandMatchResult> partition : Lists.partition(filteredResults, 1000)) {
|
|
for (List<ChannelDemandMatchResult> partition : Lists.partition(filteredResults, 1000)) {
|
|
@@ -1151,7 +1186,7 @@ public class ChannelDemandMatchJob {
|
|
|
sb.append(" AND 总uv占比 > ").append(dimensionStatMinUvRatio);
|
|
sb.append(" AND 总uv占比 > ").append(dimensionStatMinUvRatio);
|
|
|
sb.append(" AND 总访问uv > 2000 AND 全局分发pv > 10000 ");
|
|
sb.append(" AND 总访问uv > 2000 AND 全局分发pv > 10000 ");
|
|
|
// sb.append(" AND `merge二级品类` not in ('早中晚好','节日祝福') ");
|
|
// sb.append(" AND `merge二级品类` not in ('早中晚好','节日祝福') ");
|
|
|
- sb.append(" AND 维度 in ('传播的头部', '增长的头部') ");
|
|
|
|
|
|
|
+ sb.append(" AND 维度 in (").append(DimensionEnum.toSqlInValues()).append(") ");
|
|
|
// 渠道筛选
|
|
// 渠道筛选
|
|
|
if (StringUtils.hasText(config.getChannelName())) {
|
|
if (StringUtils.hasText(config.getChannelName())) {
|
|
|
sb.append(" AND 渠道类 = '").append(config.getChannelName().replace("'", "''")).append("'");
|
|
sb.append(" AND 渠道类 = '").append(config.getChannelName().replace("'", "''")).append("'");
|