diff --git a/lib/clickhouse.ts b/lib/clickhouse.ts index 959630ef..b3dc2c48 100644 --- a/lib/clickhouse.ts +++ b/lib/clickhouse.ts @@ -77,52 +77,6 @@ function getFilterQuery(filters = {}, params = {}) { return query.join('\n'); } -function getFunnelQuery( - urls: string[], - windowMinutes: number, -): { - levelQuery: string; - sumQuery: string; - urlFilterQuery: string; - urlParams: { [key: string]: string }; -} { - return urls.reduce( - (pv, cv, i) => { - const levelNumber = i + 1; - const startSum = i > 0 ? 'union all ' : ''; - const startFilter = i > 0 ? ', ' : ''; - - if (levelNumber >= 2) { - pv.levelQuery += `\n - , level${levelNumber} AS ( - select distinct y.session_id as session_id, - y.url_path as url_path, - y.referrer_path as referrer_path, - y.created_at as created_at - from level${i} x - join level0 y - on x.session_id = y.session_id - where y.created_at between x.created_at and x.created_at + interval ${windowMinutes} minute - and y.referrer_path = {url${i - 1}:String} - and y.url_path = {url${i}:String} - )`; - } - - pv.sumQuery += `\n${startSum}select ${levelNumber} as level, count(distinct(session_id)) as count from level${levelNumber}`; - pv.urlFilterQuery += `${startFilter}{url${i}:String} `; - pv.urlParams[`url${i}`] = cv; - - return pv; - }, - { - levelQuery: '', - sumQuery: '', - urlFilterQuery: '', - urlParams: {}, - }, - ); -} - function parseFilters(filters: WebsiteMetricFilter = {}, params: any = {}) { return { filterQuery: getFilterQuery(filters, params), @@ -169,7 +123,6 @@ export default { getDateQuery, getDateFormat, getFilterQuery, - getFunnelQuery, parseFilters, findUnique, findFirst, diff --git a/lib/prisma.ts b/lib/prisma.ts index 06b42acf..9b02b31b 100644 --- a/lib/prisma.ts +++ b/lib/prisma.ts @@ -19,18 +19,6 @@ const POSTGRESQL_DATE_FORMATS = { year: 'YYYY-01-01', }; -function toUuid(): string { - const db = getDatabaseType(process.env.DATABASE_URL); - - if (db === POSTGRESQL) { - return '::uuid'; - } - - if (db === MYSQL) { - return ''; - } -} - function getAddMinutesQuery(field: string, minutes: number): string { const db = getDatabaseType(process.env.DATABASE_URL); @@ -108,47 +96,6 @@ function parseFilters( }; } -function getFunnelQuery( - urls: string[], - endDate: Date, - websiteId: string, - windowMinutes: number, -): { - levelQuery: string; - sumQuery: string; -} { - return urls.reduce( - (pv, cv, i) => { - const levelNumber = i + 1; - const startSum = i > 0 ? 'union ' : ''; - - if (levelNumber >= 2) { - pv.levelQuery += `\n - , level${levelNumber} AS ( - select distinct we.session_id, we.created_at - from level${i} l - join website_event we - on l.session_id = we.session_id - where we.created_at between l.created_at - and ${getAddMinutesQuery(`l.created_at `, windowMinutes)} - and we.referrer_path = {{${i - 1}}} - and we.url_path = {{${i}}} - and we.created_at <= {{endDate}} - and we.website_id = {{websiteId}}${toUuid()} - )`; - } - - pv.sumQuery += `\n${startSum}select ${levelNumber} as level, count(distinct(session_id)) as count from level${levelNumber}`; - - return pv; - }, - { - levelQuery: '', - sumQuery: '', - }, - ); -} - async function rawQuery(sql: string, data: object): Promise { const db = getDatabaseType(); const params = []; @@ -172,8 +119,6 @@ export default { getDateQuery, getTimestampIntervalQuery, getFilterQuery, - toUuid, parseFilters, - getFunnelQuery, rawQuery, }; diff --git a/queries/analytics/reports/getFunnel.ts b/queries/analytics/reports/getFunnel.ts index e1718e84..fcaa9307 100644 --- a/queries/analytics/reports/getFunnel.ts +++ b/queries/analytics/reports/getFunnel.ts @@ -35,20 +35,64 @@ async function relationalQuery( }[] > { const { windowMinutes, startDate, endDate, urls } = criteria; - const { rawQuery, getFunnelQuery, toUuid } = prisma; - const { levelQuery, sumQuery } = getFunnelQuery(urls, endDate, websiteId, windowMinutes); + const { rawQuery, getAddMinutesQuery } = prisma; + const { levelQuery, sumQuery } = getFunnelQuery(urls, windowMinutes); + + function getFunnelQuery( + urls: string[], + windowMinutes: number, + ): { + levelQuery: string; + sumQuery: string; + } { + return urls.reduce( + (pv, cv, i) => { + const levelNumber = i + 1; + const startSum = i > 0 ? 'union ' : ''; + + if (levelNumber >= 2) { + pv.levelQuery += ` + , level${levelNumber} AS ( + select distinct we.session_id, we.created_at + from level${i} l + join website_event we + on l.session_id = we.session_id + where we.created_at between l.created_at + and ${getAddMinutesQuery(`l.created_at `, windowMinutes)} + and we.referrer_path = {{${i - 1}}} + and we.url_path = {{${i}}} + and we.created_at <= {{endDate}} + and we.website_id = {{websiteId::uuid}} + )`; + } + + pv.sumQuery += `\n${startSum}select ${levelNumber} as level, count(distinct(session_id)) as count from level${levelNumber}`; + + return pv; + }, + { + levelQuery: '', + sumQuery: '', + }, + ); + } return rawQuery( `WITH level1 AS ( select distinct session_id, created_at from website_event - where website_id = {{websiteId}}${toUuid()} + where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} and url_path = {{0}}) ${levelQuery} ${sumQuery} ORDER BY level;`, - { websiteId, startDate, endDate, ...urls }, + { + websiteId, + startDate, + endDate, + ...urls, + }, ).then(results => { return urls.map((a, i) => ({ x: a, @@ -74,15 +118,54 @@ async function clickhouseQuery( }[] > { const { windowMinutes, startDate, endDate, urls } = criteria; - const { rawQuery, getFunnelQuery } = clickhouse; + const { rawQuery } = clickhouse; const { levelQuery, sumQuery, urlFilterQuery, urlParams } = getFunnelQuery(urls, windowMinutes); - const params = { - websiteId, - startDate, - endDate, - ...urlParams, - }; + function getFunnelQuery( + urls: string[], + windowMinutes: number, + ): { + levelQuery: string; + sumQuery: string; + urlFilterQuery: string; + urlParams: { [key: string]: string }; + } { + return urls.reduce( + (pv, cv, i) => { + const levelNumber = i + 1; + const startSum = i > 0 ? 'union all ' : ''; + const startFilter = i > 0 ? ', ' : ''; + + if (levelNumber >= 2) { + pv.levelQuery += `\n + , level${levelNumber} AS ( + select distinct y.session_id as session_id, + y.url_path as url_path, + y.referrer_path as referrer_path, + y.created_at as created_at + from level${i} x + join level0 y + on x.session_id = y.session_id + where y.created_at between x.created_at and x.created_at + interval ${windowMinutes} minute + and y.referrer_path = {url${i - 1}:String} + and y.url_path = {url${i}:String} + )`; + } + + pv.sumQuery += `\n${startSum}select ${levelNumber} as level, count(distinct(session_id)) as count from level${levelNumber}`; + pv.urlFilterQuery += `${startFilter}{url${i}:String} `; + pv.urlParams[`url${i}`] = cv; + + return pv; + }, + { + levelQuery: '', + sumQuery: '', + urlFilterQuery: '', + urlParams: {}, + }, + ); + } return rawQuery<{ level: number; count: number }[]>( ` @@ -101,7 +184,12 @@ async function clickhouseQuery( from ( ${sumQuery} ) ORDER BY level;`, - params, + { + websiteId, + startDate, + endDate, + ...urlParams, + }, ).then(results => { return urls.map((a, i) => ({ x: a,