-
Notifications
You must be signed in to change notification settings - Fork 4.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
29044de
commit e440779
Showing
4 changed files
with
123 additions
and
2 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
import { canViewWebsite } from 'lib/auth'; | ||
import { useAuth, useCors, useValidate } from 'lib/middleware'; | ||
import { NextApiRequestQueryBody } from 'lib/types'; | ||
import { NextApiResponse } from 'next'; | ||
import { methodNotAllowed, ok, unauthorized } from 'next-basics'; | ||
import { getEventDataFields } from 'queries'; | ||
|
||
import * as yup from 'yup'; | ||
|
||
export interface EventDataFieldsRequestQuery { | ||
websiteId: string; | ||
startAt: string; | ||
endAt: string; | ||
} | ||
|
||
const schema = { | ||
GET: yup.object().shape({ | ||
websiteId: yup.string().uuid().required(), | ||
startAt: yup.number().integer().required(), | ||
endAt: yup.number().integer().min(yup.ref('startAt')).required(), | ||
}), | ||
}; | ||
|
||
export default async ( | ||
req: NextApiRequestQueryBody<EventDataFieldsRequestQuery>, | ||
res: NextApiResponse<any>, | ||
) => { | ||
await useCors(req, res); | ||
await useAuth(req, res); | ||
await useValidate(schema, req, res); | ||
|
||
if (req.method === 'GET') { | ||
const { websiteId, startAt, endAt } = req.query; | ||
|
||
if (!(await canViewWebsite(req.auth, websiteId))) { | ||
return unauthorized(res); | ||
} | ||
|
||
const startDate = new Date(+startAt); | ||
const endDate = new Date(+endAt); | ||
|
||
const data = await getEventDataFields(websiteId, { | ||
startDate, | ||
endDate, | ||
}); | ||
|
||
return ok(res, data); | ||
} | ||
|
||
return methodNotAllowed(res); | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import prisma from 'lib/prisma'; | ||
import clickhouse from 'lib/clickhouse'; | ||
import { CLICKHOUSE, PRISMA, runQuery } from 'lib/db'; | ||
import { QueryFilters, WebsiteEventData } from 'lib/types'; | ||
|
||
export async function getEventDataFields( | ||
...args: [websiteId: string, filters: QueryFilters] | ||
): Promise<WebsiteEventData[]> { | ||
return runQuery({ | ||
[PRISMA]: () => relationalQuery(...args), | ||
[CLICKHOUSE]: () => clickhouseQuery(...args), | ||
}); | ||
} | ||
|
||
async function relationalQuery(websiteId: string, filters: QueryFilters) { | ||
const { rawQuery, parseFilters, getDateSQL } = prisma; | ||
const { filterQuery, params } = await parseFilters(websiteId, filters); | ||
|
||
return rawQuery( | ||
` | ||
select | ||
data_key as "propertyName", | ||
data_type as "dataType", | ||
case | ||
when data_type = 2 then replace(string_value, '.0000', '') | ||
when data_type = 4 then ${getDateSQL('date_value', 'hour')} | ||
else string_value | ||
end as "value", | ||
count(*) as "total" | ||
from event_data | ||
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}} | ||
${filterQuery} | ||
group by data_key, data_type, value | ||
order by 2 desc | ||
limit 100 | ||
`, | ||
params, | ||
); | ||
} | ||
|
||
async function clickhouseQuery( | ||
websiteId: string, | ||
filters: QueryFilters, | ||
): Promise<{ propertyName: string; dataType: number; propertyValue: string; total: number }[]> { | ||
const { rawQuery, parseFilters } = clickhouse; | ||
const { filterQuery, params } = await parseFilters(websiteId, filters); | ||
|
||
return rawQuery( | ||
` | ||
select | ||
data_key as propertyName, | ||
data_type as dataType, | ||
multiIf(data_type = 2, replaceAll(string_value, '.0000', ''), | ||
data_type = 4, toString(date_trunc('hour', date_value)), | ||
string_value) as "value", | ||
count(*) as "total" | ||
from event_data | ||
where website_id = {websiteId:UUID} | ||
and created_at between {startDate:DateTime64} and {endDate:DateTime64} | ||
${filterQuery} | ||
group by data_key, data_type, value | ||
order by 2 desc | ||
limit 100 | ||
`, | ||
params, | ||
); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters