Merge branch 'dev' of https://github.com/umami-software/umami into feat/um-376-retention-report

This commit is contained in:
Francis Cao 2023-08-04 13:18:58 -07:00
commit 74b5b140ae
17 changed files with 260 additions and 469 deletions

View file

@ -1,17 +1,10 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import { WebsiteEventDataFields } from 'lib/types';
import { loadWebsite } from 'lib/load';
import { maxDate } from 'lib/date';
import { QueryFilters, WebsiteEventDataFields } from 'lib/types';
export async function getEventDataEvents(
...args: [
websiteId: string,
startDate: Date,
endDate: Date,
filters: { field?: string; event?: string },
]
...args: [websiteId: string, filters: QueryFilters & { field?: string; event?: string }]
): Promise<WebsiteEventDataFields[]> {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
@ -21,64 +14,60 @@ export async function getEventDataEvents(
async function relationalQuery(
websiteId: string,
startDate: Date,
endDate: Date,
filters: { field?: string; event?: string },
filters: QueryFilters & { field?: string; event?: string },
) {
const { rawQuery } = prisma;
const website = await loadWebsite(websiteId);
const { event } = filters;
const { rawQuery, parseFilters } = prisma;
const { params } = await parseFilters(websiteId, filters);
if (event) {
return rawQuery(
`
select
we.event_name as event,
ed.event_key as field,
ed.data_type as type,
ed.string_value as value,
website_event.event_name as event,
event_data.event_key as field,
event_data.data_type as type,
event_data.string_value as value,
count(*) as total
from event_data as ed
inner join website_event as we
on we.event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
and we.event_name = {{event}}
group by we.event_name, ed.event_key, ed.data_type, ed.string_value
from event_data
inner join website_event
on website_event.event_id = event_data.website_event_id
where event_data.website_id = {{websiteId::uuid}}
and event_data.created_at between {{startDate}} and {{endDate}}
and websit_event.event_name = {{event}}
group by website_event.event_name, event_data.event_key, event_data.data_type, event_data.string_value
order by 1 asc, 2 asc, 3 asc, 4 desc
`,
{ websiteId, startDate: maxDate(startDate, website.resetAt), endDate, ...filters },
params,
);
}
return rawQuery(
`
select
we.event_name as event,
ed.event_key as field,
ed.data_type as type,
website_event.event_name as event,
event_data.event_key as field,
event_data.data_type as type,
count(*) as total
from event_data as ed
inner join website_event as we
on we.event_id = ed.website_event_id
where ed.website_id = {{websiteId::uuid}}
and ed.created_at between {{startDate}} and {{endDate}}
group by we.event_name, ed.event_key, ed.data_type
from event_data
inner join website_event
on website_event.event_id = event_data.website_event_id
where event_data.website_id = {{websiteId::uuid}}
and event_data.created_at between {{startDate}} and {{endDate}}
group by website_event.event_name, event_data.event_key, event_data.data_type
order by 1 asc, 2 asc
limit 100
`,
{ websiteId, startDate: maxDate(startDate, website.resetAt), endDate },
params,
);
}
async function clickhouseQuery(
websiteId: string,
startDate: Date,
endDate: Date,
filters: { field?: string; event?: string },
filters: QueryFilters & { field?: string; event?: string },
) {
const { rawQuery } = clickhouse;
const website = await loadWebsite(websiteId);
const { rawQuery, parseFilters } = clickhouse;
const { event } = filters;
const { params } = await parseFilters(websiteId, filters);
if (event) {
return rawQuery(
@ -97,7 +86,7 @@ async function clickhouseQuery(
order by 1 asc, 2 asc, 3 asc, 4 desc
limit 100
`,
{ ...filters, websiteId, startDate: maxDate(startDate, website.resetAt), endDate },
params,
);
}
@ -115,6 +104,6 @@ async function clickhouseQuery(
order by 1 asc, 2 asc
limit 100
`,
{ websiteId, startDate: maxDate(startDate, website.resetAt), endDate },
params,
);
}

View file

@ -1,12 +1,10 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import { WebsiteEventDataFields } from 'lib/types';
import { loadWebsite } from 'lib/load';
import { maxDate } from 'lib/date';
import { QueryFilters, WebsiteEventDataFields } from 'lib/types';
export async function getEventDataFields(
...args: [websiteId: string, startDate: Date, endDate: Date, field?: string]
...args: [websiteId: string, filters: QueryFilters & { field?: string }]
): Promise<WebsiteEventDataFields[]> {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
@ -14,9 +12,10 @@ export async function getEventDataFields(
});
}
async function relationalQuery(websiteId: string, startDate: Date, endDate: Date, field: string) {
const { rawQuery } = prisma;
const website = await loadWebsite(websiteId);
async function relationalQuery(websiteId: string, filters: QueryFilters & { field?: string }) {
const { rawQuery, parseFilters } = prisma;
const { field } = filters;
const { params } = await parseFilters(websiteId, filters);
if (field) {
return rawQuery(
@ -33,7 +32,7 @@ async function relationalQuery(websiteId: string, startDate: Date, endDate: Date
order by 3 desc, 2 desc, 1 asc
limit 100
`,
{ websiteId, field, startDate: maxDate(startDate, website.resetAt), endDate },
params,
);
}
@ -50,13 +49,14 @@ async function relationalQuery(websiteId: string, startDate: Date, endDate: Date
order by 3 desc, 2 asc, 1 asc
limit 100
`,
{ websiteId, startDate: maxDate(startDate, website.resetAt), endDate },
params,
);
}
async function clickhouseQuery(websiteId: string, startDate: Date, endDate: Date, field: string) {
const { rawQuery } = clickhouse;
const website = await loadWebsite(websiteId);
async function clickhouseQuery(websiteId: string, filters: QueryFilters & { field?: string }) {
const { rawQuery, parseFilters } = clickhouse;
const { field } = filters;
const { params } = await parseFilters(websiteId, filters);
if (field) {
return rawQuery(
@ -73,7 +73,7 @@ async function clickhouseQuery(websiteId: string, startDate: Date, endDate: Date
order by 3 desc, 2 desc, 1 asc
limit 100
`,
{ websiteId, field, startDate: maxDate(startDate, website.resetAt), endDate },
params,
);
}
@ -90,6 +90,6 @@ async function clickhouseQuery(websiteId: string, startDate: Date, endDate: Date
order by 3 desc, 2 asc, 1 asc
limit 100
`,
{ websiteId, startDate: maxDate(startDate, website.resetAt), endDate },
params,
);
}

View file

@ -1,24 +1,11 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import { WebsiteEventMetric } from 'lib/types';
import { WebsiteEventMetric, QueryFilters } from 'lib/types';
import { EVENT_TYPE } from 'lib/constants';
import { loadWebsite } from 'lib/load';
import { maxDate } from 'lib/date';
export interface GetEventMetricsCriteria {
startDate: Date;
endDate: Date;
timezone: string;
unit: string;
filters: {
url: string;
eventName: string;
};
}
export async function getEventMetrics(
...args: [websiteId: string, criteria: GetEventMetricsCriteria]
...args: [websiteId: string, criteria: QueryFilters]
): Promise<WebsiteEventMetric[]> {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
@ -26,11 +13,13 @@ export async function getEventMetrics(
});
}
async function relationalQuery(websiteId: string, criteria: GetEventMetricsCriteria) {
const { startDate, endDate, timezone = 'utc', unit = 'day', filters } = criteria;
const { rawQuery, getDateQuery, getFilterQuery } = prisma;
const website = await loadWebsite(websiteId);
const filterQuery = getFilterQuery(filters);
async function relationalQuery(websiteId: string, filters: QueryFilters) {
const { timezone = 'utc', unit = 'day' } = filters;
const { rawQuery, getDateQuery, parseFilters } = prisma;
const { filterQuery, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.customEvent,
});
return rawQuery(
`
@ -46,22 +35,17 @@ async function relationalQuery(websiteId: string, criteria: GetEventMetricsCrite
group by 1, 2
order by 2
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.customEvent,
domain: website.domain,
},
params,
);
}
async function clickhouseQuery(websiteId: string, criteria: GetEventMetricsCriteria) {
const { startDate, endDate, timezone = 'utc', unit = 'day', filters } = criteria;
const { rawQuery, getDateQuery, getFilterQuery } = clickhouse;
const website = await loadWebsite(websiteId);
const filterQuery = getFilterQuery(filters);
async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
const { timezone = 'utc', unit = 'day' } = filters;
const { rawQuery, getDateQuery, parseFilters } = clickhouse;
const { filterQuery, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.customEvent,
});
return rawQuery(
`
@ -77,13 +61,6 @@ async function clickhouseQuery(websiteId: string, criteria: GetEventMetricsCrite
group by x, t
order by t
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.customEvent,
domain: website.domain,
},
params,
);
}

View file

@ -2,19 +2,10 @@ import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import { EVENT_TYPE } from 'lib/constants';
import { loadWebsite } from 'lib/load';
import { maxDate } from 'lib/date';
import { QueryFilters } from 'lib/types';
export async function getPageviewMetrics(
...args: [
websiteId: string,
criteria: {
startDate: Date;
endDate: Date;
column: string;
filters: object;
},
]
...args: [websiteId: string, columns: string, filters: QueryFilters]
) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
@ -22,20 +13,12 @@ export async function getPageviewMetrics(
});
}
async function relationalQuery(
websiteId: string,
criteria: {
startDate: Date;
endDate: Date;
column: string;
filters: object;
},
) {
const { startDate, endDate, filters = {}, column } = criteria;
async function relationalQuery(websiteId: string, column: string, filters: QueryFilters) {
const { rawQuery, parseFilters } = prisma;
const website = await loadWebsite(websiteId);
const { filterQuery, joinSession } = parseFilters(filters);
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
...filters,
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -50,31 +33,16 @@ async function relationalQuery(
order by 2 desc
limit 100
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
domain: website.domain,
},
params,
);
}
async function clickhouseQuery(
websiteId: string,
criteria: {
startDate: Date;
endDate: Date;
column: string;
filters: object;
},
) {
const { startDate, endDate, filters = {}, column } = criteria;
async function clickhouseQuery(websiteId: string, column: string, filters: QueryFilters) {
const { rawQuery, parseFilters } = clickhouse;
const website = await loadWebsite(websiteId);
const { filterQuery } = parseFilters(filters);
const { filterQuery, params } = await parseFilters(websiteId, {
...filters,
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -88,13 +56,6 @@ async function clickhouseQuery(
order by y desc
limit 100
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: column === 'event_name' ? EVENT_TYPE.customEvent : EVENT_TYPE.pageView,
domain: website.domain,
},
params,
);
}

View file

@ -2,43 +2,22 @@ import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
import { EVENT_TYPE } from 'lib/constants';
import { loadWebsite } from 'lib/load';
import { maxDate } from 'lib/date';
import { QueryFilters } from 'lib/types';
export interface PageviewStatsCriteria {
startDate: Date;
endDate: Date;
timezone?: string;
unit?: string;
filters: {
url?: string;
referrer?: string;
title?: string;
browser?: string;
os?: string;
device?: string;
screen?: string;
language?: string;
country?: string;
region?: string;
city?: string;
};
}
export async function getPageviewStats(
...args: [websiteId: string, criteria: PageviewStatsCriteria]
) {
export async function getPageviewStats(...args: [websiteId: string, filters: QueryFilters]) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(websiteId: string, criteria: PageviewStatsCriteria) {
const { startDate, endDate, timezone = 'utc', unit = 'day', filters = {} } = criteria;
async function relationalQuery(websiteId: string, filters: QueryFilters) {
const { timezone = 'utc', unit = 'day' } = filters;
const { getDateQuery, parseFilters, rawQuery } = prisma;
const website = await loadWebsite(websiteId);
const { filterQuery, joinSession } = parseFilters(filters);
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -53,22 +32,17 @@ async function relationalQuery(websiteId: string, criteria: PageviewStatsCriteri
${filterQuery}
group by 1
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
domain: website.domain,
},
params,
);
}
async function clickhouseQuery(websiteId: string, criteria: PageviewStatsCriteria) {
const { startDate, endDate, timezone = 'UTC', unit = 'day', filters = {} } = criteria;
async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
const { timezone = 'UTC', unit = 'day' } = filters;
const { parseFilters, rawQuery, getDateStringQuery, getDateQuery } = clickhouse;
const website = await loadWebsite(websiteId);
const { filterQuery } = parseFilters(filters);
const { filterQuery, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -88,13 +62,6 @@ async function clickhouseQuery(websiteId: string, criteria: PageviewStatsCriteri
) as g
order by t
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
domain: website.domain,
},
params,
);
}

View file

@ -1,19 +1,10 @@
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { maxDate } from 'lib/date';
import { EVENT_TYPE } from 'lib/constants';
import { loadWebsite } from 'lib/load';
import { QueryFilters } from 'lib/types';
export interface GetInsightsCriteria {
startDate: Date;
endDate: Date;
fields: { name: string; type: string; value: string }[];
filters: string[];
groups: string[];
}
export async function getInsights(...args: [websiteId: string, criteria: GetInsightsCriteria]) {
export async function getInsights(...args: [websiteId: string, filters: QueryFilters]) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
@ -22,18 +13,18 @@ export async function getInsights(...args: [websiteId: string, criteria: GetInsi
async function relationalQuery(
websiteId: string,
criteria: GetInsightsCriteria,
filters: QueryFilters,
): Promise<
{
x: string;
y: number;
}[]
> {
const { startDate, endDate, filters = [] } = criteria;
const { parseFilters, rawQuery } = prisma;
const website = await loadWebsite(websiteId);
const params = {};
const { filterQuery, joinSession } = parseFilters(params);
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -48,37 +39,30 @@ async function relationalQuery(
${filterQuery}
group by 1
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
},
params,
);
}
async function clickhouseQuery(
websiteId: string,
criteria: GetInsightsCriteria,
filters: QueryFilters,
): Promise<
{
x: string;
y: number;
}[]
> {
const { startDate, endDate, fields = [], filters = [], groups = [] } = criteria;
const { parseFilters, rawQuery } = clickhouse;
const website = await loadWebsite(websiteId);
const params = {};
const { filterQuery } = parseFilters(params);
const fieldsQuery = parseFields(fields);
const { fields } = filters;
const { filterQuery, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
select
${fieldsQuery}
${parseFields(fields)}
from website_event
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime} and {endDate:DateTime}
@ -88,13 +72,7 @@ async function clickhouseQuery(
order by total desc
limit 500
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
},
params,
);
}

View file

@ -2,14 +2,10 @@ import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import { EVENT_TYPE } from 'lib/constants';
import { loadWebsite } from 'lib/load';
import { maxDate } from 'lib/date';
import { QueryFilters } from 'lib/types';
export async function getSessionMetrics(
...args: [
websiteId: string,
criteria: { startDate: Date; endDate: Date; column: string; filters: object },
]
...args: [websiteId: string, column: string, filters: QueryFilters]
) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
@ -17,14 +13,12 @@ export async function getSessionMetrics(
});
}
async function relationalQuery(
websiteId: string,
criteria: { startDate: Date; endDate: Date; column: string; filters: object },
) {
const website = await loadWebsite(websiteId);
const { startDate, endDate, column, filters = {} } = criteria;
async function relationalQuery(websiteId: string, column: string, filters: QueryFilters) {
const { parseFilters, rawQuery } = prisma;
const { filterQuery, joinSession } = parseFilters(filters);
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`select ${column} x, count(*) y
@ -32,28 +26,22 @@ async function relationalQuery(
${joinSession}
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
group by 1
order by 2 desc
limit 100`,
{
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
...filters,
},
params,
);
}
async function clickhouseQuery(
websiteId: string,
data: { startDate: Date; endDate: Date; column: string; filters: object },
) {
const { startDate, endDate, column, filters = {} } = data;
async function clickhouseQuery(websiteId: string, column: string, filters: QueryFilters) {
const { parseFilters, rawQuery } = clickhouse;
const website = await loadWebsite(websiteId);
const { filterQuery } = parseFilters(filters);
const { filterQuery, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -68,12 +56,6 @@ async function clickhouseQuery(
order by y desc
limit 100
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
},
params,
);
}

View file

@ -2,43 +2,22 @@ import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
import { EVENT_TYPE } from 'lib/constants';
import { loadWebsite } from 'lib/load';
import { maxDate } from 'lib/date';
import { QueryFilters } from 'lib/types';
export interface SessionStatsCriteria {
startDate: Date;
endDate: Date;
timezone?: string;
unit?: string;
filters: {
url?: string;
referrer?: string;
title?: string;
browser?: string;
os?: string;
device?: string;
screen?: string;
language?: string;
country?: string;
region?: string;
city?: string;
};
}
export async function getSessionStats(
...args: [websiteId: string, criteria: SessionStatsCriteria]
) {
export async function getSessionStats(...args: [websiteId: string, filters: QueryFilters]) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(websiteId: string, criteria: SessionStatsCriteria) {
const { startDate, endDate, timezone = 'utc', unit = 'day', filters = {} } = criteria;
async function relationalQuery(websiteId: string, filters: QueryFilters) {
const { timezone = 'utc', unit = 'day' } = filters;
const { getDateQuery, parseFilters, rawQuery } = prisma;
const website = await loadWebsite(websiteId);
const { filterQuery, joinSession } = parseFilters(filters);
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -53,22 +32,17 @@ async function relationalQuery(websiteId: string, criteria: SessionStatsCriteria
${filterQuery}
group by 1
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
domain: website.domain,
},
params,
);
}
async function clickhouseQuery(websiteId: string, criteria: SessionStatsCriteria) {
const { startDate, endDate, timezone = 'UTC', unit = 'day', filters = {} } = criteria;
async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
const { timezone = 'UTC', unit = 'day' } = filters;
const { parseFilters, rawQuery, getDateStringQuery, getDateQuery } = clickhouse;
const website = await loadWebsite(websiteId);
const { filterQuery } = parseFilters(filters);
const { filterQuery, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -88,13 +62,6 @@ async function clickhouseQuery(websiteId: string, criteria: SessionStatsCriteria
) as g
order by t
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
domain: website.domain,
},
params,
);
}

View file

@ -1,9 +1,7 @@
import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import { loadWebsite } from 'lib/load';
import { DEFAULT_RESET_DATE } from 'lib/constants';
import { maxDate } from 'lib/date';
export async function getWebsiteDateRange(...args: [websiteId: string]) {
return runQuery({
@ -13,8 +11,8 @@ export async function getWebsiteDateRange(...args: [websiteId: string]) {
}
async function relationalQuery(websiteId: string) {
const { rawQuery } = prisma;
const website = await loadWebsite(websiteId);
const { rawQuery, parseFilters } = prisma;
const { params } = await parseFilters(websiteId, { startDate: new Date(DEFAULT_RESET_DATE) });
const result = await rawQuery(
`
@ -25,15 +23,15 @@ async function relationalQuery(websiteId: string) {
where website_id = {{websiteId::uuid}}
and created_at >= {{startDate}}
`,
{ websiteId, startDate: maxDate(new Date(DEFAULT_RESET_DATE), new Date(website.resetAt)) },
params,
);
return result[0] ?? null;
}
async function clickhouseQuery(websiteId: string) {
const { rawQuery } = clickhouse;
const website = await loadWebsite(websiteId);
const { rawQuery, parseFilters } = clickhouse;
const { params } = await parseFilters(websiteId, { startDate: new Date(DEFAULT_RESET_DATE) });
const result = await rawQuery(
`
@ -44,7 +42,7 @@ async function clickhouseQuery(websiteId: string) {
where website_id = {websiteId:UUID}
and created_at >= {startDate:DateTime}
`,
{ websiteId, startDate: maxDate(new Date(DEFAULT_RESET_DATE), new Date(website.resetAt)) },
params,
);
return result[0] ?? null;

View file

@ -2,29 +2,21 @@ import prisma from 'lib/prisma';
import clickhouse from 'lib/clickhouse';
import { runQuery, CLICKHOUSE, PRISMA } from 'lib/db';
import { EVENT_TYPE } from 'lib/constants';
import { loadWebsite } from 'lib/load';
import { maxDate } from 'lib/date';
import { QueryFilters } from 'lib/types';
export async function getWebsiteStats(
...args: [
websiteId: string,
data: { startDate: Date; endDate: Date; type?: string; filters: object },
]
) {
export async function getWebsiteStats(...args: [websiteId: string, filters: QueryFilters]) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(
websiteId: string,
criteria: { startDate: Date; endDate: Date; filters: object },
) {
const { startDate, endDate, filters = {} } = criteria;
async function relationalQuery(websiteId: string, filters: QueryFilters) {
const { getDateQuery, getTimestampIntervalQuery, parseFilters, rawQuery } = prisma;
const website = await loadWebsite(websiteId);
const { filterQuery, joinSession } = parseFilters(filters);
const { filterQuery, joinSession, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -43,32 +35,23 @@ async function relationalQuery(
join website
on website_event.website_id = website.website_id
${joinSession}
where event_type = {{eventType}}
and website.website_id = {{websiteId::uuid}}
where website.website_id = {{websiteId::uuid}}
and website_event.created_at between {{startDate}} and {{endDate}}
and event_type = {{eventType}}
${filterQuery}
group by 1, 2
) as t
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
domain: website.domain,
},
params,
);
}
async function clickhouseQuery(
websiteId: string,
criteria: { startDate: Date; endDate: Date; filters: object },
) {
const { startDate, endDate, filters = {} } = criteria;
async function clickhouseQuery(websiteId: string, filters: QueryFilters) {
const { rawQuery, getDateQuery, parseFilters } = clickhouse;
const website = await loadWebsite(websiteId);
const { filterQuery } = parseFilters(filters);
const { filterQuery, params } = await parseFilters(websiteId, {
...filters,
eventType: EVENT_TYPE.pageView,
});
return rawQuery(
`
@ -92,13 +75,6 @@ async function clickhouseQuery(
group by session_id, time_series
) as t;
`,
{
...filters,
websiteId,
startDate: maxDate(startDate, website.resetAt),
endDate,
eventType: EVENT_TYPE.pageView,
domain: website.domain,
},
params,
);
}