refactor Property components to be resused for both session/event data. Implement session-data screens + filtering. Remove all event-data specific compoenents/queries
This commit is contained in:
1 parent
9da332c489
commit
680a1ca1a2
71 files changed
+2814
-958
No files matched your search
@@ -29,13 +29,13 @@ async function relationalQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
const { timezone = 'utc', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getEventPropertyFilterQuery } = prisma;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
@@ -57,11 +57,11 @@ async function relationalQuery(
|
||||
and event_data.data_key = {{propertyName}}
|
||||
and event_data.data_type = ${DATA_TYPE.array}
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by 1, 2
|
||||
order by 2
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -74,9 +74,9 @@ async function clickhouseQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getEventPropertyFilterQuery } = clickhouse;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
@@ -101,11 +101,11 @@ async function clickhouseQuery(
|
||||
and event_data.data_key = {propertyName:String}
|
||||
and event_data.data_type = ${DATA_TYPE.array}
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by x, t
|
||||
order by t
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -29,13 +29,13 @@ async function relationalQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
) : Promise<EventDataDateSeriesPoint[]> {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters, getDateStringSQL, getEventPropertyFilterQuery } = prisma;
|
||||
const { rawQuery, parseFilters, getDateStringSQL, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
@@ -55,11 +55,11 @@ async function relationalQuery(
|
||||
and event_data.data_key = {{propertyName}}
|
||||
and event_data.data_type = ${DATA_TYPE.date}
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by 1
|
||||
order by 1
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -72,9 +72,9 @@ async function clickhouseQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
): Promise<EventDataDateSeriesPoint[]> {
|
||||
const { timezone = 'UTC' } = filters;
|
||||
const { rawQuery, parseFilters, getDateStringSQL, getEventPropertyFilterQuery } = clickhouse;
|
||||
const { rawQuery, parseFilters, getDateStringSQL, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
@@ -98,11 +98,11 @@ async function clickhouseQuery(
|
||||
and event_data.data_key = {propertyName:String}
|
||||
and event_data.data_type = ${DATA_TYPE.date}
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by t
|
||||
order by t
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -30,13 +30,13 @@ async function relationalQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
) {
|
||||
const { timezone = 'utc', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getEventPropertyFilterQuery } = prisma;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
const aggSql =
|
||||
metric === 'avg' ? 'avg(cast(event_data.number_value as decimal))' :
|
||||
metric === 'count' ? 'count(*)' :
|
||||
@@ -60,11 +60,11 @@ async function relationalQuery(
|
||||
and event_data.data_key = {{propertyName}}
|
||||
and event_data.data_type = 2
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by 1
|
||||
order by 1
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -78,9 +78,9 @@ async function clickhouseQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
): Promise<{ t: string; y: number }[]> {
|
||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getEventPropertyFilterQuery } = clickhouse;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
const aggSql =
|
||||
metric === 'avg' ? 'avg(event_data.number_value)' :
|
||||
metric === 'count' ? 'count()' :
|
||||
@@ -108,11 +108,11 @@ async function clickhouseQuery(
|
||||
and event_data.data_key = {propertyName:String}
|
||||
and event_data.data_type = 2
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by t
|
||||
order by t
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -28,13 +28,13 @@ async function relationalQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
) {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters, getEventPropertyFilterQuery } = prisma;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
@@ -57,9 +57,9 @@ async function relationalQuery(
|
||||
and event_data.data_key = {{propertyName}}
|
||||
and event_data.data_type = 2
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -72,9 +72,9 @@ async function clickhouseQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
): Promise<EventDataNumericStats[]> {
|
||||
const { timezone = 'UTC' } = filters;
|
||||
const { rawQuery, parseFilters, getEventPropertyFilterQuery } = clickhouse;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
@@ -101,9 +101,9 @@ async function clickhouseQuery(
|
||||
and event_data.data_key = {propertyName:String}
|
||||
and event_data.data_type = 2
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -22,7 +22,7 @@ export async function getEventDataPivot(
|
||||
|
||||
async function relationalQuery(websiteId: string, eventName: string, filters: QueryFilters, eventFilters: EventPropertyFilter[] = []) {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters, getEventPropertyFilterQuery } = prisma;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { page = 1, pageSize } = filters;
|
||||
const size = +pageSize || DEFAULT_PAGE_SIZE;
|
||||
const offset = +size * (+page - 1);
|
||||
@@ -32,7 +32,7 @@ async function relationalQuery(websiteId: string, eventName: string, filters: Qu
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
const countResult = await rawQuery(
|
||||
`
|
||||
@@ -47,9 +47,9 @@ async function relationalQuery(websiteId: string, eventName: string, filters: Qu
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_name = {{eventName}}
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
`,
|
||||
{ ...queryParams, eventName, ...epfParams },
|
||||
{ ...queryParams, eventName, ...pfParams },
|
||||
);
|
||||
|
||||
const count = countResult[0].num;
|
||||
@@ -68,7 +68,7 @@ async function relationalQuery(websiteId: string, eventName: string, filters: Qu
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and website_event.event_name = {{eventName}}
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by website_event.event_id
|
||||
order by max(website_event.created_at) desc
|
||||
limit ${size} offset ${offset}
|
||||
@@ -97,7 +97,7 @@ async function relationalQuery(websiteId: string, eventName: string, filters: Qu
|
||||
and event_data.created_at between {{startDate}} and {{endDate}}
|
||||
order by website_event.created_at desc
|
||||
`,
|
||||
{ ...queryParams, eventName, ...epfParams },
|
||||
{ ...queryParams, eventName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
|
||||
@@ -120,13 +120,13 @@ async function relationalQuery(websiteId: string, eventName: string, filters: Qu
|
||||
|
||||
async function clickhouseQuery(websiteId: string, eventName: string, filters: QueryFilters, eventFilters: EventPropertyFilter[] = []) {
|
||||
const { timezone = 'UTC' } = filters;
|
||||
const { rawQuery, parseFilters, getEventPropertyFilterQuery } = clickhouse;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { page = 1, pageSize } = filters;
|
||||
const size = +pageSize || DEFAULT_PAGE_SIZE;
|
||||
const offset = +size * (+page - 1);
|
||||
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
const count = await rawQuery(
|
||||
`
|
||||
@@ -146,9 +146,9 @@ async function clickhouseQuery(websiteId: string, eventName: string, filters: Qu
|
||||
where event_data_pivot.website_id = {websiteId:UUID}
|
||||
and event_data_pivot.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
`,
|
||||
{ ...queryParams, eventName, ...epfParams },
|
||||
{ ...queryParams, eventName, ...pfParams },
|
||||
).then((res: any) => res[0].num);
|
||||
|
||||
const data = await rawQuery(
|
||||
@@ -176,7 +176,7 @@ async function clickhouseQuery(websiteId: string, eventName: string, filters: Qu
|
||||
where event_data_pivot.website_id = {websiteId:UUID}
|
||||
and event_data_pivot.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by
|
||||
event_data_pivot.event_id,
|
||||
event_data_pivot.session_id,
|
||||
@@ -186,7 +186,7 @@ async function clickhouseQuery(websiteId: string, eventName: string, filters: Qu
|
||||
order by event_data_pivot.created_at desc
|
||||
limit ${size} offset ${offset}
|
||||
`,
|
||||
{ ...queryParams, eventName, ...epfParams },
|
||||
{ ...queryParams, eventName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
|
||||
|
||||
@@ -29,13 +29,13 @@ async function relationalQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
const { timezone = 'utc', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getEventPropertyFilterQuery } = prisma;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
@@ -56,11 +56,11 @@ async function relationalQuery(
|
||||
and event_data.data_key = {{propertyName}}
|
||||
and event_data.data_type in (${DATA_TYPE.string}, ${DATA_TYPE.boolean})
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by 1, 2
|
||||
order by 2
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -73,9 +73,9 @@ async function clickhouseQuery(
|
||||
eventFilters: EventPropertyFilter[] = [],
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getEventPropertyFilterQuery } = clickhouse;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: epfSQL, params: epfParams } = getEventPropertyFilterQuery(eventFilters, timezone);
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(eventFilters, 'event', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
@@ -100,11 +100,11 @@ async function clickhouseQuery(
|
||||
and event_data.data_key = {propertyName:String}
|
||||
and event_data.data_type in (${DATA_TYPE.string}, ${DATA_TYPE.boolean})
|
||||
${filterQuery}
|
||||
${epfSQL}
|
||||
${pfSQL}
|
||||
group by x, t
|
||||
order by t
|
||||
`,
|
||||
{ ...queryParams, eventName, propertyName, ...epfParams },
|
||||
{ ...queryParams, eventName, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -76,6 +76,7 @@ async function relationalQuery(
|
||||
where event_data.website_id = {{websiteId::uuid}}
|
||||
and event_data.created_at between {{startDate}} and {{endDate}}
|
||||
and event_data.data_key = {{propertyName}}
|
||||
${dataType ? `and event_data.data_type = ${dataType}` : ''}
|
||||
${filterQuery}
|
||||
group by value
|
||||
order by 2 desc
|
||||
@@ -146,6 +147,7 @@ async function clickhouseQuery(
|
||||
where event_data.website_id = {websiteId:UUID}
|
||||
and event_data.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and event_data.data_key = {propertyName:String}
|
||||
${dataType ? `and event_data.data_type = ${dataType}` : ''}
|
||||
${filterQuery}
|
||||
group by value
|
||||
order by 2 desc
|
||||
|
||||
@@ -41,7 +41,14 @@ export * from './reports/getUTM';
|
||||
export * from './sessions/createSession';
|
||||
export * from './sessions/getSessionActivity';
|
||||
export * from './sessions/getSessionData';
|
||||
export * from './sessions/getSessionDataArraySeries';
|
||||
export * from './sessions/getSessionDataDateSeries';
|
||||
export * from './sessions/getSessionDataProperties';
|
||||
export * from './sessions/getSessionDataPropertySeries';
|
||||
export * from './sessions/getSessionDataNumericSeries';
|
||||
export * from './sessions/getSessionDataNumericStats';
|
||||
export * from './sessions/getSessionDataPivot';
|
||||
export * from './sessions/getSessionDataStats';
|
||||
export * from './sessions/getSessionDataValues';
|
||||
export * from './sessions/getSessionExpandedMetrics';
|
||||
export * from './sessions/getSessionMetrics';
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { DATA_TYPE } from '@/lib/constants';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { EventDataSeriesPoint, PropertyFilter, QueryFilters } from '@/lib/types';
|
||||
|
||||
const FUNCTION_NAME = 'getSessionDataArraySeries';
|
||||
|
||||
export async function getSessionDataArraySeries(
|
||||
...args: [
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters?: PropertyFilter[],
|
||||
]
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
const { timezone = 'utc', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
array_item.value as x,
|
||||
${getDateSQL('session_data.created_at', unit, timezone)} as t,
|
||||
count(distinct session_data.session_id) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
join session_data
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = website_event.website_id
|
||||
cross join lateral jsonb_array_elements_text(coalesce(session_data.string_value, '[]')::jsonb) as array_item(value)
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
and session_data.data_type = ${DATA_TYPE.array}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
group by 1, 2
|
||||
order by 2
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
arrayJoin(JSONExtract(ifNull(session_data.string_value, '[]'), 'Array(String)')) as x,
|
||||
${getDateSQL('session_data.created_at', unit, timezone)} as t,
|
||||
uniq(session_data.session_id) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
join session_data final
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = {websiteId:UUID}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
and session_data.data_type = ${DATA_TYPE.array}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
group by x, t
|
||||
order by t
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,96 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { DATA_TYPE } from '@/lib/constants';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { EventDataDateSeriesPoint, PropertyFilter, QueryFilters } from '@/lib/types';
|
||||
|
||||
const FUNCTION_NAME = 'getSessionDataDateSeries';
|
||||
|
||||
export async function getSessionDataDateSeries(
|
||||
...args: [
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters?: PropertyFilter[],
|
||||
]
|
||||
): Promise<EventDataDateSeriesPoint[]> {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<EventDataDateSeriesPoint[]> {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters, getDateStringSQL, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
${getDateStringSQL('session_data.date_value', 'second', timezone)} as t,
|
||||
count(distinct session_data.session_id) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
join session_data
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = website_event.website_id
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
and session_data.data_type = ${DATA_TYPE.date}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
group by 1
|
||||
order by 1
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<EventDataDateSeriesPoint[]> {
|
||||
const { timezone = 'UTC' } = filters;
|
||||
const { rawQuery, parseFilters, getDateStringSQL, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
${getDateStringSQL('session_data.date_value', 'second', timezone)} as t,
|
||||
uniq(session_data.session_id) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
join session_data final
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = {websiteId:UUID}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
and session_data.data_type = ${DATA_TYPE.date}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
group by t
|
||||
order by t
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,119 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { PropertyFilter, QueryFilters } from '@/lib/types';
|
||||
|
||||
const FUNCTION_NAME = 'getSessionDataNumericSeries';
|
||||
|
||||
export async function getSessionDataNumericSeries(
|
||||
...args: [
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
metric: 'sum' | 'avg' | 'count',
|
||||
filters: QueryFilters,
|
||||
propertyFilters?: PropertyFilter[],
|
||||
]
|
||||
) {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
metric: 'sum' | 'avg' | 'count',
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
) {
|
||||
const { timezone = 'utc', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
const aggSql =
|
||||
metric === 'avg'
|
||||
? 'avg(cast(session_data.number_value as decimal))'
|
||||
: metric === 'count'
|
||||
? 'count(distinct session_data.session_id)'
|
||||
: 'sum(cast(session_data.number_value as decimal))';
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id, website_event.website_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
)
|
||||
select
|
||||
${getDateSQL('session_data.created_at', unit, timezone)} t,
|
||||
${aggSql} y
|
||||
from session_data
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
and filtered_sessions.website_id = session_data.website_id
|
||||
where session_data.website_id = {{websiteId::uuid}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
and session_data.data_type = 2
|
||||
group by 1
|
||||
order by 1
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
metric: 'sum' | 'avg' | 'count',
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<{ t: string; y: number }[]> {
|
||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
const aggSql =
|
||||
metric === 'avg'
|
||||
? 'avg(session_data.number_value)'
|
||||
: metric === 'count'
|
||||
? 'uniq(session_data.session_id)'
|
||||
: 'sum(session_data.number_value)';
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
)
|
||||
select
|
||||
${getDateSQL('session_data.created_at', unit, timezone)} as t,
|
||||
${aggSql} as y
|
||||
from session_data final
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {websiteId:UUID}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
and session_data.data_type = 2
|
||||
group by t
|
||||
order by t
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { EventDataNumericStats, PropertyFilter, QueryFilters } from '@/lib/types';
|
||||
|
||||
const FUNCTION_NAME = 'getSessionDataNumericStats';
|
||||
|
||||
export async function getSessionDataNumericStats(
|
||||
...args: [
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters?: PropertyFilter[],
|
||||
]
|
||||
): Promise<EventDataNumericStats> {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
}).then(results => results?.[0]);
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
) {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id, website_event.website_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
)
|
||||
select
|
||||
coalesce(sum(cast(session_data.number_value as decimal)), 0) as "total",
|
||||
coalesce(avg(cast(session_data.number_value as decimal)), 0) as "average",
|
||||
coalesce(percentile_cont(0.5) within group (order by session_data.number_value), 0) as "median",
|
||||
coalesce(max(session_data.number_value), 0) as "max",
|
||||
coalesce(min(session_data.number_value), 0) as "min"
|
||||
from session_data
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
and filtered_sessions.website_id = session_data.website_id
|
||||
where session_data.website_id = {{websiteId::uuid}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
and session_data.data_type = 2
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<EventDataNumericStats[]> {
|
||||
const { timezone = 'UTC' } = filters;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
)
|
||||
select
|
||||
if(count() = 0, 0, sum(session_data.number_value)) as total,
|
||||
if(count() = 0, 0, avg(session_data.number_value)) as average,
|
||||
if(count() = 0, 0, median(session_data.number_value)) as median,
|
||||
if(count() = 0, 0, max(session_data.number_value)) as max,
|
||||
if(count() = 0, 0, min(session_data.number_value)) as min
|
||||
from session_data final
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {websiteId:UUID}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
and session_data.data_type = 2
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { DEFAULT_PAGE_SIZE } from '@/lib/constants';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { PageResult, PropertyFilter, QueryFilters, SessionDataPivotRow } from '@/lib/types';
|
||||
|
||||
const FUNCTION_NAME = 'getSessionDataPivot';
|
||||
|
||||
export async function getSessionDataPivot(
|
||||
...args: [
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters?: PropertyFilter[],
|
||||
]
|
||||
): Promise<PageResult<SessionDataPivotRow[]>> {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<PageResult<SessionDataPivotRow[]>> {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { page = 1, pageSize } = filters;
|
||||
const size = +pageSize || DEFAULT_PAGE_SIZE;
|
||||
const offset = +size * (+page - 1);
|
||||
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
|
||||
propertyFilters,
|
||||
'session',
|
||||
timezone,
|
||||
);
|
||||
|
||||
const countResult = await rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
),
|
||||
selected_property_sessions as (
|
||||
select distinct session_data.session_id
|
||||
from session_data
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {{websiteId::uuid}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
)
|
||||
select count(*) as num
|
||||
from selected_property_sessions
|
||||
`,
|
||||
{ ...queryParams, websiteId, propertyName, ...pfParams },
|
||||
);
|
||||
|
||||
const count = countResult[0].num;
|
||||
|
||||
const rows = await rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
),
|
||||
selected_property_sessions as (
|
||||
select distinct session_data.session_id
|
||||
from session_data
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {{websiteId::uuid}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
),
|
||||
paged_sessions as (
|
||||
select session_data.session_id
|
||||
from session_data
|
||||
join selected_property_sessions
|
||||
on selected_property_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {{websiteId::uuid}}
|
||||
group by session_data.session_id
|
||||
order by max(session_data.created_at) desc
|
||||
limit ${size} offset ${offset}
|
||||
)
|
||||
select
|
||||
session_data.session_id as "sessionId",
|
||||
coalesce(max(session_data.distinct_id), '') as "distinctId",
|
||||
max(session_data.created_at) as "createdAt",
|
||||
array_agg(session_data.data_key order by session_data.data_key asc) as "propertyKeys",
|
||||
array_agg(
|
||||
coalesce(
|
||||
case when session_data.data_type = 1 then session_data.string_value end,
|
||||
case when session_data.data_type = 2 then cast(session_data.number_value as varchar) end,
|
||||
case when session_data.data_type = 3 then session_data.string_value end,
|
||||
case when session_data.data_type = 4 then cast(session_data.date_value as varchar) end,
|
||||
case when session_data.data_type = 5 then session_data.string_value end,
|
||||
''
|
||||
)
|
||||
order by session_data.data_key asc
|
||||
) as "propertyValues"
|
||||
from session_data
|
||||
join paged_sessions on paged_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {{websiteId::uuid}}
|
||||
group by session_data.session_id
|
||||
order by max(session_data.created_at) desc
|
||||
`,
|
||||
{ ...queryParams, websiteId, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
|
||||
return { data: rows, count, page: +page, pageSize: size };
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<PageResult<SessionDataPivotRow[]>> {
|
||||
const { timezone = 'UTC' } = filters;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { page = 1, pageSize } = filters;
|
||||
const size = +pageSize || DEFAULT_PAGE_SIZE;
|
||||
const offset = +size * (+page - 1);
|
||||
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
|
||||
propertyFilters,
|
||||
'session',
|
||||
timezone,
|
||||
);
|
||||
|
||||
const count = await rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
),
|
||||
selected_property_sessions as (
|
||||
select distinct session_data.session_id
|
||||
from session_data final
|
||||
join filtered_sessions on filtered_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {websiteId:UUID}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
)
|
||||
select count() as num
|
||||
from selected_property_sessions
|
||||
`,
|
||||
{ ...queryParams, websiteId, propertyName, ...pfParams },
|
||||
).then((res: any) => res[0].num);
|
||||
|
||||
const data = await rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
),
|
||||
selected_property_sessions as (
|
||||
select distinct session_data.session_id
|
||||
from session_data final
|
||||
join filtered_sessions on filtered_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {websiteId:UUID}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
)
|
||||
select
|
||||
session_data_pivot.session_id as sessionId,
|
||||
session_data_pivot.distinct_id as distinctId,
|
||||
maxMerge(session_data_pivot.created_at) as createdAt,
|
||||
groupArrayMerge(session_data_pivot.property_keys) as propertyKeys,
|
||||
groupArrayMerge(session_data_pivot.property_values) as propertyValues
|
||||
from umami.session_data_pivot session_data_pivot
|
||||
join selected_property_sessions
|
||||
on selected_property_sessions.session_id = session_data_pivot.session_id
|
||||
where session_data_pivot.website_id = {websiteId:UUID}
|
||||
group by
|
||||
session_data_pivot.session_id,
|
||||
session_data_pivot.distinct_id
|
||||
order by createdAt desc
|
||||
limit ${size} offset ${offset}
|
||||
`,
|
||||
{ ...queryParams, websiteId, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
|
||||
return { data, count, page: +page, pageSize: size };
|
||||
}
|
||||
@@ -1,12 +1,17 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { QueryFilters } from '@/lib/types';
|
||||
import type { PropertyFilter, QueryFilters } from '@/lib/types';
|
||||
|
||||
const FUNCTION_NAME = 'getSessionDataProperties';
|
||||
|
||||
export async function getSessionDataProperties(
|
||||
...args: [websiteId: string, filters: QueryFilters]
|
||||
...args: [
|
||||
websiteId: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters?: PropertyFilter[],
|
||||
selectedPropertyName?: string,
|
||||
]
|
||||
) {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
@@ -14,32 +19,58 @@ export async function getSessionDataProperties(
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
const { rawQuery, parseFilters } = prisma;
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
selectedPropertyName?: string,
|
||||
) {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
|
||||
propertyFilters,
|
||||
'session',
|
||||
timezone,
|
||||
);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id, website_event.website_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
),
|
||||
selected_property_sessions as (
|
||||
select distinct session_data.session_id, session_data.website_id
|
||||
from session_data
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
and filtered_sessions.website_id = session_data.website_id
|
||||
${selectedPropertyName ? 'where session_data.data_key = {{selectedPropertyName}}' : ''}
|
||||
)
|
||||
select
|
||||
data_key as "propertyName",
|
||||
data_type as "dataType",
|
||||
count(distinct session_data.session_id) as "total"
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
from selected_property_sessions
|
||||
join session_data
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = website_event.website_id
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
group by 1
|
||||
order by 2 desc
|
||||
on session_data.session_id = selected_property_sessions.session_id
|
||||
and session_data.website_id = selected_property_sessions.website_id
|
||||
group by 1, 2
|
||||
order by 3 desc, 1 asc
|
||||
limit 500
|
||||
`,
|
||||
queryParams,
|
||||
{ ...queryParams, websiteId, selectedPropertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -47,29 +78,52 @@ async function relationalQuery(websiteId: string, filters: QueryFilters) {
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
filters: QueryFilters,
|
||||
): Promise<{ propertyName: string; total: number }[]> {
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId });
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
selectedPropertyName?: string,
|
||||
): Promise<{ propertyName: string; dataType: number; total: number }[]> {
|
||||
const { timezone = 'UTC' } = filters;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(
|
||||
propertyFilters,
|
||||
'session',
|
||||
timezone,
|
||||
);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id, website_event.website_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
),
|
||||
selected_property_sessions as (
|
||||
select distinct session_data.session_id, session_data.website_id
|
||||
from session_data final
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
and filtered_sessions.website_id = session_data.website_id
|
||||
${selectedPropertyName ? 'where session_data.data_key = {selectedPropertyName:String}' : ''}
|
||||
)
|
||||
select
|
||||
data_key as propertyName,
|
||||
data_type as dataType,
|
||||
count(distinct session_data.session_id) as total
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
from selected_property_sessions
|
||||
join session_data final
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = {websiteId:UUID}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
on session_data.session_id = selected_property_sessions.session_id
|
||||
and session_data.website_id = selected_property_sessions.website_id
|
||||
where session_data.website_id = {websiteId:UUID}
|
||||
and session_data.data_key != ''
|
||||
${filterQuery}
|
||||
group by 1
|
||||
order by 2 desc
|
||||
group by 1, 2
|
||||
order by 3 desc, 1 asc
|
||||
limit 500
|
||||
`,
|
||||
queryParams,
|
||||
{ ...queryParams, websiteId, selectedPropertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { DATA_TYPE } from '@/lib/constants';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { EventDataSeriesPoint, PropertyFilter, QueryFilters } from '@/lib/types';
|
||||
|
||||
const FUNCTION_NAME = 'getSessionDataPropertySeries';
|
||||
|
||||
export async function getSessionDataPropertySeries(
|
||||
...args: [
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters?: PropertyFilter[],
|
||||
]
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
const { timezone = 'utc', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
session_data.string_value as x,
|
||||
${getDateSQL('session_data.created_at', unit, timezone)} t,
|
||||
count(distinct session_data.session_id) y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
join session_data
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = website_event.website_id
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
and session_data.data_type in (${DATA_TYPE.string}, ${DATA_TYPE.boolean})
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
group by 1, 2
|
||||
order by 2
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
): Promise<EventDataSeriesPoint[]> {
|
||||
const { timezone = 'UTC', unit = 'day' } = filters;
|
||||
const { rawQuery, getDateSQL, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
session_data.string_value as x,
|
||||
${getDateSQL('session_data.created_at', unit, timezone)} as t,
|
||||
uniq(session_data.session_id) as y
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
join session_data final
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = {websiteId:UUID}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
and session_data.data_type in (${DATA_TYPE.string}, ${DATA_TYPE.boolean})
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
group by x, t
|
||||
order by t
|
||||
`,
|
||||
{ ...queryParams, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,185 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { DATA_TYPE } from '@/lib/constants';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { PropertyFilter, PropertyLeaderboardRow, QueryFilters } from '@/lib/types';
|
||||
|
||||
const FUNCTION_NAME = 'getSessionDataStats';
|
||||
|
||||
export async function getSessionDataStats(
|
||||
...args: [websiteId: string, propertyName: string, filters: QueryFilters, propertyFilters?: PropertyFilter[]]
|
||||
): Promise<PropertyLeaderboardRow[]> {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
[CLICKHOUSE]: () => clickhouseQuery(...args),
|
||||
});
|
||||
}
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
) {
|
||||
const { timezone = 'utc' } = filters;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery, getTimestampDiffSQL } = prisma;
|
||||
const { filterQuery, cohortQuery, joinSessionQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
timezone,
|
||||
});
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id, website_event.website_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
),
|
||||
session_rollup as (
|
||||
select
|
||||
website_event.session_id,
|
||||
website_event.visit_id,
|
||||
count(*) as activity,
|
||||
sum(case when website_event.event_type = 1 then 1 else 0 end) as views,
|
||||
sum(case when website_event.event_type = 2 then 1 else 0 end) as events,
|
||||
min(website_event.created_at) as min_time,
|
||||
max(website_event.created_at) as max_time
|
||||
from website_event
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = website_event.session_id
|
||||
and filtered_sessions.website_id = website_event.website_id
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
group by website_event.session_id, website_event.visit_id
|
||||
),
|
||||
session_stats as (
|
||||
select
|
||||
session_id,
|
||||
count(*) as visits,
|
||||
sum(activity) as activity,
|
||||
sum(views) as views,
|
||||
sum(events) as events,
|
||||
sum(${getTimestampDiffSQL('min_time', 'max_time')}) as totaltime
|
||||
from session_rollup
|
||||
group by session_id
|
||||
),
|
||||
property_values as (
|
||||
select
|
||||
session_data.session_id,
|
||||
session_data.string_value as value
|
||||
from session_data
|
||||
join filtered_sessions
|
||||
on filtered_sessions.session_id = session_data.session_id
|
||||
and filtered_sessions.website_id = session_data.website_id
|
||||
where session_data.website_id = {{websiteId::uuid}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
and session_data.data_type = ${DATA_TYPE.string}
|
||||
and coalesce(session_data.string_value, '') != ''
|
||||
)
|
||||
select
|
||||
property_values.value as label,
|
||||
coalesce(sum(session_stats.activity), 0) as activity,
|
||||
count(distinct property_values.session_id) as sessions,
|
||||
coalesce(sum(session_stats.visits), 0) as visits,
|
||||
coalesce(sum(session_stats.views), 0) as views,
|
||||
coalesce(sum(session_stats.events), 0) as events,
|
||||
coalesce(sum(session_stats.totaltime), 0) as totaltime,
|
||||
coalesce(sum(case when session_stats.visits = 1 then 1 else 0 end), 0) as "newSessions",
|
||||
coalesce(sum(case when session_stats.visits > 1 then 1 else 0 end), 0) as "returningSessions"
|
||||
from property_values
|
||||
join session_stats on session_stats.session_id = property_values.session_id
|
||||
group by property_values.value
|
||||
order by activity desc, property_values.value asc
|
||||
limit 100
|
||||
`,
|
||||
{ ...queryParams, websiteId, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
propertyName: string,
|
||||
filters: QueryFilters,
|
||||
propertyFilters: PropertyFilter[] = [],
|
||||
) {
|
||||
const { timezone = 'UTC' } = filters;
|
||||
const { rawQuery, parseFilters, getPropertyFilterQuery } = clickhouse;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId, timezone });
|
||||
const { sql: pfSQL, params: pfParams } = getPropertyFilterQuery(propertyFilters, 'session', timezone);
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
with filtered_sessions as (
|
||||
select distinct website_event.session_id
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
${filterQuery}
|
||||
${pfSQL}
|
||||
),
|
||||
session_rollup as (
|
||||
select
|
||||
website_event.session_id,
|
||||
website_event.visit_id,
|
||||
count() as activity,
|
||||
sumIf(1, website_event.event_type = 1) as views,
|
||||
sumIf(1, website_event.event_type = 2) as events,
|
||||
min(website_event.created_at) as min_time,
|
||||
max(website_event.created_at) as max_time
|
||||
from website_event
|
||||
join filtered_sessions on filtered_sessions.session_id = website_event.session_id
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
group by website_event.session_id, website_event.visit_id
|
||||
),
|
||||
session_stats as (
|
||||
select
|
||||
session_id,
|
||||
count() as visits,
|
||||
sum(activity) as activity,
|
||||
sum(views) as views,
|
||||
sum(events) as events,
|
||||
sum(max_time - min_time) as totaltime
|
||||
from session_rollup
|
||||
group by session_id
|
||||
),
|
||||
property_values as (
|
||||
select
|
||||
session_data.session_id,
|
||||
session_data.string_value as value
|
||||
from session_data final
|
||||
join filtered_sessions on filtered_sessions.session_id = session_data.session_id
|
||||
where session_data.website_id = {websiteId:UUID}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
and session_data.data_type = ${DATA_TYPE.string}
|
||||
and ifNull(session_data.string_value, '') != ''
|
||||
)
|
||||
select
|
||||
property_values.value as label,
|
||||
ifNull(sum(session_stats.activity), 0) as activity,
|
||||
uniq(property_values.session_id) as sessions,
|
||||
ifNull(sum(session_stats.visits), 0) as visits,
|
||||
ifNull(sum(session_stats.views), 0) as views,
|
||||
ifNull(sum(session_stats.events), 0) as events,
|
||||
ifNull(sum(session_stats.totaltime), 0) as totaltime,
|
||||
ifNull(sum(if(session_stats.visits = 1, 1, 0)), 0) as newSessions,
|
||||
ifNull(sum(if(session_stats.visits > 1, 1, 0)), 0) as returningSessions
|
||||
from property_values
|
||||
join session_stats on session_stats.session_id = property_values.session_id
|
||||
group by property_values.value
|
||||
order by activity desc, property_values.value asc
|
||||
limit 100
|
||||
`,
|
||||
{ ...queryParams, websiteId, propertyName, ...pfParams },
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import clickhouse from '@/lib/clickhouse';
|
||||
import { DATA_TYPE } from '@/lib/constants';
|
||||
import { CLICKHOUSE, PRISMA, runQuery } from '@/lib/db';
|
||||
import prisma from '@/lib/prisma';
|
||||
import type { QueryFilters } from '@/lib/types';
|
||||
@@ -6,7 +7,7 @@ import type { QueryFilters } from '@/lib/types';
|
||||
const FUNCTION_NAME = 'getSessionDataValues';
|
||||
|
||||
export async function getSessionDataValues(
|
||||
...args: [websiteId: string, filters: QueryFilters & { propertyName?: string }]
|
||||
...args: [websiteId: string, filters: QueryFilters & { propertyName?: string; dataType?: number }]
|
||||
) {
|
||||
return runQuery({
|
||||
[PRISMA]: () => relationalQuery(...args),
|
||||
@@ -16,14 +17,42 @@ export async function getSessionDataValues(
|
||||
|
||||
async function relationalQuery(
|
||||
websiteId: string,
|
||||
filters: QueryFilters & { propertyName?: string },
|
||||
filters: QueryFilters & { propertyName?: string; dataType?: number },
|
||||
) {
|
||||
const { rawQuery, parseFilters, getDateSQL } = prisma;
|
||||
const { dataType } = filters;
|
||||
const { filterQuery, joinSessionQuery, cohortQuery, queryParams } = parseFilters({
|
||||
...filters,
|
||||
websiteId,
|
||||
});
|
||||
|
||||
if (dataType === DATA_TYPE.array) {
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
array_item.value as "value",
|
||||
count(distinct session_data.session_id) as "total"
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
${joinSessionQuery}
|
||||
join session_data
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = website_event.website_id
|
||||
cross join lateral jsonb_array_elements_text(coalesce(session_data.string_value, '[]')::jsonb) as array_item(value)
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
and session_data.data_type = ${DATA_TYPE.array}
|
||||
${filterQuery}
|
||||
group by array_item.value
|
||||
order by 2 desc
|
||||
limit 100
|
||||
`,
|
||||
queryParams,
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
@@ -42,6 +71,7 @@ async function relationalQuery(
|
||||
where website_event.website_id = {{websiteId::uuid}}
|
||||
and website_event.created_at between {{startDate}} and {{endDate}}
|
||||
and session_data.data_key = {{propertyName}}
|
||||
${dataType ? `and session_data.data_type = ${dataType}` : ''}
|
||||
${filterQuery}
|
||||
group by value
|
||||
order by 2 desc
|
||||
@@ -54,11 +84,37 @@ async function relationalQuery(
|
||||
|
||||
async function clickhouseQuery(
|
||||
websiteId: string,
|
||||
filters: QueryFilters & { propertyName?: string },
|
||||
filters: QueryFilters & { propertyName?: string; dataType?: number },
|
||||
): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> {
|
||||
const { rawQuery, parseFilters } = clickhouse;
|
||||
const { dataType } = filters;
|
||||
const { filterQuery, cohortQuery, queryParams } = parseFilters({ ...filters, websiteId });
|
||||
|
||||
if (dataType === DATA_TYPE.array) {
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
arrayJoin(JSONExtract(ifNull(session_data.string_value, '[]'), 'Array(String)')) as "value",
|
||||
uniq(session_data.session_id) as "total"
|
||||
from website_event
|
||||
${cohortQuery}
|
||||
join session_data final
|
||||
on session_data.session_id = website_event.session_id
|
||||
and session_data.website_id = {websiteId:UUID}
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
and session_data.data_type = ${DATA_TYPE.array}
|
||||
${filterQuery}
|
||||
group by value
|
||||
order by 2 desc
|
||||
limit 100
|
||||
`,
|
||||
queryParams,
|
||||
FUNCTION_NAME,
|
||||
);
|
||||
}
|
||||
|
||||
return rawQuery(
|
||||
`
|
||||
select
|
||||
@@ -74,6 +130,7 @@ async function clickhouseQuery(
|
||||
where website_event.website_id = {websiteId:UUID}
|
||||
and website_event.created_at between {startDate:DateTime64} and {endDate:DateTime64}
|
||||
and session_data.data_key = {propertyName:String}
|
||||
${dataType ? `and session_data.data_type = ${dataType}` : ''}
|
||||
${filterQuery}
|
||||
group by value
|
||||
order by 2 desc
|
||||
|
||||
Reference in new issue
Block a user