From 85f29d8b49c6f8bce5883fcefc2ce662b0457f47 Mon Sep 17 00:00:00 2001 From: William Tso Date: Thu, 10 Apr 2025 18:31:24 +0800 Subject: [PATCH] click subpath match --- app/api/events/utm/route.ts | 29 +++++++++++++++++------------ lib/clickhouse.ts | 26 ++++++++++++++++---------- 2 files changed, 33 insertions(+), 22 deletions(-) diff --git a/app/api/events/utm/route.ts b/app/api/events/utm/route.ts index aa1cd51..052fda8 100644 --- a/app/api/events/utm/route.ts +++ b/app/api/events/utm/route.ts @@ -66,23 +66,28 @@ export async function GET(request: NextRequest) { conditions.push(`link_id = '${linkId}'`); } - // 添加子路径筛选 - if (subpath) { + // 添加子路径筛选 - 使用更精确的匹配方式 + if (subpath && subpath.trim() !== '') { console.log('====== UTM API SUBPATH DEBUG ======'); console.log('Raw subpath param:', subpath); - console.log('Subpath type:', typeof subpath); - console.log('Subpath length:', subpath.length); - console.log('Subpath chars:', Array.from(subpath).map(c => c.charCodeAt(0))); - // 确保没有前导斜杠,避免双斜杠问题 - const cleanSubpath = subpath.startsWith('/') - ? subpath.substring(1) - : subpath; - + // 清理并准备subpath值 + let cleanSubpath = subpath.trim(); + // 移除开头的斜杠以便匹配 + if (cleanSubpath.startsWith('/')) { + cleanSubpath = cleanSubpath.substring(1); + } + // 移除结尾的斜杠以便匹配 + if (cleanSubpath.endsWith('/')) { + cleanSubpath = cleanSubpath.substring(0, cleanSubpath.length - 1); + } + console.log('Cleaned subpath:', cleanSubpath); - // 在event_attributes JSON的full_url字段中查找subpath - const condition = `JSONExtractString(event_attributes, 'full_url') LIKE '%${cleanSubpath}%'`; + // 使用正则表达式匹配URL中的第二个路径部分 + // 示例: 在 "https://abc.com/slug/subpath/" 中匹配 "subpath" + const condition = `match(JSONExtractString(event_attributes, 'full_url'), '/[^/]+/${cleanSubpath}(/|\\\\?|$)')`; + console.log('Final SQL condition:', condition); console.log('=================================='); diff --git a/lib/clickhouse.ts b/lib/clickhouse.ts index 1ff5e1b..bdde8c2 100644 --- a/lib/clickhouse.ts +++ b/lib/clickhouse.ts @@ -58,22 +58,28 @@ export function buildFilter(params: Partial): string { filters.push(`user_id = '${params.userId}'`); } - // 添加子路径过滤条件 - if (params.subpath) { + // 添加子路径过滤条件 - 使用更精确的匹配方式 + if (params.subpath && params.subpath.trim() !== '') { console.log('====== SUBPATH DEBUG ======'); console.log('Raw subpath param:', params.subpath); - console.log('Subpath type:', typeof params.subpath); - console.log('Subpath length:', params.subpath.length); - // 确保子路径没有前导斜杠,避免双斜杠问题 - const cleanSubpath = params.subpath.startsWith('/') - ? params.subpath.substring(1) - : params.subpath; + // 清理并准备subpath值 + let cleanSubpath = params.subpath.trim(); + // 移除开头的斜杠以便匹配 + if (cleanSubpath.startsWith('/')) { + cleanSubpath = cleanSubpath.substring(1); + } + // 移除结尾的斜杠以便匹配 + if (cleanSubpath.endsWith('/')) { + cleanSubpath = cleanSubpath.substring(0, cleanSubpath.length - 1); + } console.log('Cleaned subpath:', cleanSubpath); - // 在event_attributes JSON的full_url字段中查找subpath - const condition = `JSONExtractString(event_attributes, 'full_url') LIKE '%${cleanSubpath}%'`; + // 使用正则表达式匹配URL中的第二个路径部分 + // 示例: 在 "https://abc.com/slug/subpath/" 中匹配 "subpath" + const condition = `match(JSONExtractString(event_attributes, 'full_url'), '/[^/]+/${cleanSubpath}(/|\\\\?|$)')`; + console.log('Final SQL condition:', condition); console.log('==========================');