diff --git a/lib/prisma.ts b/lib/prisma.ts index d1b9d0e5..50f26f75 100644 --- a/lib/prisma.ts +++ b/lib/prisma.ts @@ -4,7 +4,7 @@ import { MYSQL, POSTGRESQL, getDatabaseType } from 'lib/db'; import { FILTER_COLUMNS, IGNORED_FILTERS, SESSION_COLUMNS } from './constants'; import { loadWebsite } from './load'; import { maxDate } from './date'; -import { QueryFilters } from './types'; +import { QueryFilters, QueryOptions } from './types'; const MYSQL_DATE_FORMATS = { minute: '%Y-%m-%d %H:%i:00', @@ -74,12 +74,12 @@ function getFilterQuery(filters = {}): string { if (filter !== undefined && !IGNORED_FILTERS.includes(key)) { const column = FILTER_COLUMNS[key] || key; arr.push(`and ${column}={{${key}}}`); - } - if (key === 'referrer') { - arr.push( - 'and (website_event.referrer_domain != {{websiteDomain}} or website_event.referrer_domain is null)', - ); + if (key === 'referrer') { + arr.push( + 'and (website_event.referrer_domain != {{websiteDomain}} or website_event.referrer_domain is null)', + ); + } } return arr; @@ -88,13 +88,18 @@ function getFilterQuery(filters = {}): string { return query.join('\n'); } -async function parseFilters(websiteId, filters: QueryFilters & { [key: string]: any } = {}) { +async function parseFilters( + websiteId, + filters: QueryFilters & { [key: string]: any } = {}, + options: QueryOptions = {}, +) { const website = await loadWebsite(websiteId); return { - joinSession: Object.keys(filters).find(key => SESSION_COLUMNS[key]) - ? `inner join session on website_event.session_id = session.session_id` - : '', + joinSession: + options?.joinSession || Object.keys(filters).find(key => SESSION_COLUMNS.includes(key)) + ? `inner join session on website_event.session_id = session.session_id` + : '', filterQuery: getFilterQuery(filters), params: { ...filters, diff --git a/lib/types.ts b/lib/types.ts index 131740f8..3ce852ae 100644 --- a/lib/types.ts +++ b/lib/types.ts @@ -137,11 +137,11 @@ export interface QueryFilters { unit?: string; domain?: string; eventType?: number; + eventName?: string; url?: string; referrer?: string; title?: string; query?: string; - event?: string; os?: string; browser?: string; device?: string; @@ -150,3 +150,7 @@ export interface QueryFilters { city?: string; language?: string; } + +export interface QueryOptions { + joinSession?: boolean; +} diff --git a/pages/api/websites/[id]/events.ts b/pages/api/websites/[id]/events.ts index b9e3ac71..7d4f999f 100644 --- a/pages/api/websites/[id]/events.ts +++ b/pages/api/websites/[id]/events.ts @@ -43,10 +43,8 @@ export default async ( endDate, timezone, unit, - filters: { - url, - eventName, - }, + url, + eventName, }); return ok(res, events); diff --git a/queries/analytics/events/getEventMetrics.ts b/queries/analytics/events/getEventMetrics.ts index cf862f4a..09a85946 100644 --- a/queries/analytics/events/getEventMetrics.ts +++ b/queries/analytics/events/getEventMetrics.ts @@ -5,7 +5,7 @@ import { WebsiteEventMetric, QueryFilters } from 'lib/types'; import { EVENT_TYPE } from 'lib/constants'; export async function getEventMetrics( - ...args: [websiteId: string, criteria: QueryFilters] + ...args: [websiteId: string, filters: QueryFilters] ): Promise { return runQuery({ [PRISMA]: () => relationalQuery(...args), @@ -16,7 +16,7 @@ export async function getEventMetrics( async function relationalQuery(websiteId: string, filters: QueryFilters) { const { timezone = 'utc', unit = 'day' } = filters; const { rawQuery, getDateQuery, parseFilters } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, joinSession, params } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.customEvent, }); @@ -28,6 +28,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { ${getDateQuery('created_at', unit, timezone)} t, count(*) y from website_event + ${joinSession} where website_id = {{websiteId::uuid}} and created_at between {{startDate}} and {{endDate}} and event_type = {{eventType}} diff --git a/queries/analytics/pageviews/getPageviewMetrics.ts b/queries/analytics/pageviews/getPageviewMetrics.ts index bbbd7705..b365d3f6 100644 --- a/queries/analytics/pageviews/getPageviewMetrics.ts +++ b/queries/analytics/pageviews/getPageviewMetrics.ts @@ -1,7 +1,7 @@ import prisma from 'lib/prisma'; import clickhouse from 'lib/clickhouse'; import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db'; -import { EVENT_TYPE } from 'lib/constants'; +import { EVENT_TYPE, SESSION_COLUMNS } from 'lib/constants'; import { QueryFilters } from 'lib/types'; export async function getPageviewMetrics( @@ -15,16 +15,20 @@ export async function getPageviewMetrics( async function relationalQuery(websiteId: string, column: string, filters: QueryFilters) { const { rawQuery, parseFilters } = prisma; - const { filterQuery, joinSession, params } = await parseFilters(websiteId, { - ...filters, - eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, - }); + const { filterQuery, joinSession, params } = await parseFilters( + websiteId, + { + ...filters, + eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView, + }, + { joinSession: SESSION_COLUMNS.includes(column) }, + ); return rawQuery( ` select ${column} x, count(*) y from website_event - ${joinSession} + ${joinSession} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} and event_type = {{eventType}} diff --git a/queries/analytics/sessions/getSessionMetrics.ts b/queries/analytics/sessions/getSessionMetrics.ts index 5ef387ec..fb546a73 100644 --- a/queries/analytics/sessions/getSessionMetrics.ts +++ b/queries/analytics/sessions/getSessionMetrics.ts @@ -1,7 +1,7 @@ import prisma from 'lib/prisma'; import clickhouse from 'lib/clickhouse'; import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db'; -import { EVENT_TYPE } from 'lib/constants'; +import { EVENT_TYPE, SESSION_COLUMNS } from 'lib/constants'; import { QueryFilters } from 'lib/types'; export async function getSessionMetrics( @@ -15,21 +15,26 @@ export async function getSessionMetrics( async function relationalQuery(websiteId: string, column: string, filters: QueryFilters) { const { parseFilters, rawQuery } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, { - ...filters, - eventType: EVENT_TYPE.pageView, - }); + const { filterQuery, joinSession, params } = await parseFilters( + websiteId, + { + ...filters, + eventType: EVENT_TYPE.pageView, + }, + { + joinSession: SESSION_COLUMNS.includes(column), + }, + ); return rawQuery( - `select ${column} x, count(*) y - from website_event - inner join session - on session.session_id = website_event.session_id - where website_event.website_id = {{websiteId::uuid}} - and website_event.created_at between {{startDate}} and {{endDate}} - and website_event.event_type = {{eventType}} - ${filterQuery} - ) as t + ` + select ${column} x, count(*) y + from website_event + ${joinSession} + where website_event.website_id = {{websiteId::uuid}} + and website_event.created_at between {{startDate}} and {{endDate}} + and website_event.event_type = {{eventType}} + ${filterQuery} group by 1 order by 2 desc limit 100`, diff --git a/queries/analytics/sessions/getSessionStats.ts b/queries/analytics/sessions/getSessionStats.ts index b8884a44..9ed01a59 100644 --- a/queries/analytics/sessions/getSessionStats.ts +++ b/queries/analytics/sessions/getSessionStats.ts @@ -14,7 +14,7 @@ export async function getSessionStats(...args: [websiteId: string, filters: Quer async function relationalQuery(websiteId: string, filters: QueryFilters) { const { timezone = 'utc', unit = 'day' } = filters; const { getDateQuery, parseFilters, rawQuery } = prisma; - const { filterQuery, params } = await parseFilters(websiteId, { + const { filterQuery, joinSession, params } = await parseFilters(websiteId, { ...filters, eventType: EVENT_TYPE.pageView, }); @@ -25,8 +25,7 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) { ${getDateQuery('website_event.created_at', unit, timezone)} x, count(distinct website_event.session_id) y from website_event - inner join session - on session.session_id = website_event.session_id + ${joinSession} where website_event.website_id = {{websiteId::uuid}} and website_event.created_at between {{startDate}} and {{endDate}} and event_type = {{eventType}}