umami/src/queries/analytics/reports/getJourney.ts

144 lines
3.7 KiB
TypeScript
Raw Normal View History

2024-05-17 08:42:36 +00:00
import clickhouse from 'lib/clickhouse';
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db';
import prisma from 'lib/prisma';
2024-06-01 18:45:06 +00:00
interface JourneyResult {
e1: string;
e2: string;
e3: string;
e4: string;
e5: string;
count: string;
}
2024-05-17 08:42:36 +00:00
export async function getJourney(
...args: [
websiteId: string,
filters: {
startDate: Date;
endDate: Date;
},
]
) {
return runQuery({
[PRISMA]: () => relationalQuery(...args),
[CLICKHOUSE]: () => clickhouseQuery(...args),
});
}
async function relationalQuery(
websiteId: string,
filters: {
startDate: Date;
endDate: Date;
},
2024-06-01 18:45:06 +00:00
): Promise<JourneyResult[]> {
2024-05-17 08:42:36 +00:00
const { startDate, endDate } = filters;
const { rawQuery } = prisma;
return rawQuery(
`
WITH events AS (
select distinct
session_id,
referrer_path,
COALESCE(event_name, url_path) event,
ROW_NUMBER() OVER (PARTITION BY session_id ORDER BY created_at) AS event_number
from website_event
where website_id = {{websiteId::uuid}}
and created_at between {{startDate}} and {{endDate}}
and referrer_path != url_path),
sequences as (
SELECT s.e1,
s.e2,
s.e3,
s.e4,
s.e5,
count(*) count
FROM (
SELECT session_id,
MAX(CASE WHEN event_number = 1 THEN event ELSE NULL END) AS e1,
MAX(CASE WHEN event_number = 2 THEN event ELSE NULL END) AS e2,
MAX(CASE WHEN event_number = 3 THEN event ELSE NULL END) AS e3,
MAX(CASE WHEN event_number = 4 THEN event ELSE NULL END) AS e4,
MAX(CASE WHEN event_number = 5 THEN event ELSE NULL END) AS e5
FROM events
group by session_id) s
group by s.e1,
s.e2,
s.e3,
s.e4,
s.e5)
select *
from sequences
order by count desc
limit 100
`,
{
websiteId,
startDate,
endDate,
},
2024-06-01 18:45:06 +00:00
).then(parseResult);
2024-05-17 08:42:36 +00:00
}
async function clickhouseQuery(
websiteId: string,
filters: {
startDate: Date;
endDate: Date;
},
2024-06-01 18:45:06 +00:00
): Promise<JourneyResult[]> {
2024-05-17 08:42:36 +00:00
const { startDate, endDate } = filters;
const { rawQuery } = clickhouse;
return rawQuery(
`
WITH events AS (
select distinct
session_id,
referrer_path,
coalesce(nullIf(event_name, ''), url_path) event,
row_number() OVER (PARTITION BY session_id ORDER BY created_at) AS event_number
from umami.website_event
where website_id = {websiteId:UUID}
and created_at between {startDate:DateTime64} and {endDate:DateTime64}
and referrer_path != url_path),
sequences as (
SELECT s.e1,
s.e2,
s.e3,
s.e4,
s.e5,
count(*) count
FROM (
SELECT session_id,
max(CASE WHEN event_number = 1 THEN event ELSE NULL END) AS e1,
max(CASE WHEN event_number = 2 THEN event ELSE NULL END) AS e2,
max(CASE WHEN event_number = 3 THEN event ELSE NULL END) AS e3,
max(CASE WHEN event_number = 4 THEN event ELSE NULL END) AS e4,
max(CASE WHEN event_number = 5 THEN event ELSE NULL END) AS e5
FROM events
group by session_id) s
group by s.e1,
s.e2,
s.e3,
s.e4,
s.e5)
select *
from sequences
order by count desc
limit 100
`,
{
websiteId,
startDate,
endDate,
},
2024-06-01 18:45:06 +00:00
).then(parseResult);
}
function parseResult(data: any) {
return data.map(({ e1, e2, e3, e4, e5, count }) => ({ items: [e1, e2, e3, e4, e5], count }));
2024-05-17 08:42:36 +00:00
}