diff --git a/lib/prisma.ts b/lib/prisma.ts index e250987e..5177acc2 100644 --- a/lib/prisma.ts +++ b/lib/prisma.ts @@ -32,7 +32,7 @@ function toUuid(): string { } } -function getAddMinutesQuery(field: string, minutes: number) { +function getAddMinutesQuery(field: string, minutes: number): string { const db = getDatabaseType(process.env.DATABASE_URL); if (db === POSTGRESQL) { @@ -134,13 +134,49 @@ function getFilterQuery(filters = {}, params = []): string { return query.join('\n'); } +function parseFilters( + filters: { [key: string]: any } = {}, + params = [], + sessionKey = 'session_id', +) { + const { os, browser, device, country, region, city } = filters; + + return { + joinSession: + os || browser || device || country || region || city + ? `inner join session on website_event.${sessionKey} = session.${sessionKey}` + : '', + filterQuery: getFilterQuery(filters, params), + }; +} + +function getFunnelParams(endDate: Date, websiteId: string, urls: string[]): any[] { + const db = getDatabaseType(process.env.DATABASE_URL); + + if (db === POSTGRESQL) { + return urls; + } + + if (db === MYSQL) { + let params = []; + params.push(urls[0]); + for (let i = 0; i < urls.length - 1; i++) { + params = params.concat([urls[i], urls[i + 1], endDate, websiteId]); + } + + return params; + } +} + function getFunnelQuery( urls: string[], + endDate: Date, + websiteId: string, windowMinutes: number, ): { levelQuery: string; sumQuery: string; - urlFilterQuery: string; + urlParams: any[]; } { const initParamLength = 3; @@ -148,7 +184,6 @@ function getFunnelQuery( (pv, cv, i) => { const levelNumber = i + 1; const startSum = i > 0 ? 'union ' : ''; - const startFilter = i > 0 ? ', ' : ''; if (levelNumber >= 2) { pv.levelQuery += `\n @@ -167,35 +202,18 @@ function getFunnelQuery( } pv.sumQuery += `\n${startSum}select ${levelNumber} as level, count(distinct(session_id)) as count from level${levelNumber}`; - - pv.urlFilterQuery += `${startFilter}$${levelNumber + initParamLength} `; + pv.urlParams = getFunnelParams(endDate, websiteId, urls); return pv; }, { levelQuery: '', sumQuery: '', - urlFilterQuery: '', + urlParams: [], }, ); } -function parseFilters( - filters: { [key: string]: any } = {}, - params = [], - sessionKey = 'session_id', -) { - const { os, browser, device, country, region, city } = filters; - - return { - joinSession: - os || browser || device || country || region || city - ? `inner join session on website_event.${sessionKey} = session.${sessionKey}` - : '', - filterQuery: getFilterQuery(filters, params), - }; -} - async function rawQuery(query: string, params: never[] = []): Promise { const db = getDatabaseType(process.env.DATABASE_URL); @@ -214,9 +232,10 @@ export default { getDateQuery, getTimestampInterval, getFilterQuery, - getFunnelQuery, getEventDataFilterQuery, toUuid, parseFilters, + getFunnelParams, + getFunnelQuery, rawQuery, }; diff --git a/queries/analytics/pageview/getPageviewFunnel.ts b/queries/analytics/pageview/getPageviewFunnel.ts index 3af1545a..bdfb1c5b 100644 --- a/queries/analytics/pageview/getPageviewFunnel.ts +++ b/queries/analytics/pageview/getPageviewFunnel.ts @@ -36,16 +36,20 @@ async function relationalQuery( > { const { windowMinutes, startDate, endDate, urls } = criteria; const { rawQuery, getFunnelQuery, toUuid } = prisma; - const { levelQuery, sumQuery, urlFilterQuery } = getFunnelQuery(urls, windowMinutes); + const { levelQuery, sumQuery, urlParams } = getFunnelQuery( + urls, + endDate, + websiteId, + windowMinutes, + ); - const params: any = [websiteId, startDate, endDate, ...urls]; + const params: any = [websiteId, startDate, endDate, ...urlParams]; return rawQuery( `WITH level1 AS ( select distinct session_id, created_at from website_event - where url_path in (${urlFilterQuery}) - and website_id = $1${toUuid()} + where website_id = $1${toUuid()} and created_at between $2 and $3 and url_path = $4) ${levelQuery}