Refactor query methods.

This commit is contained in:
Mike Cao 2020-09-24 23:02:11 -07:00
parent ee8859d86c
commit 1dfa6d8b16
2 changed files with 92 additions and 205 deletions

View File

@ -31,9 +31,3 @@ if (process.env.NODE_ENV === 'production') {
}
export default prisma;
export async function runQuery(query) {
return query.catch(e => {
throw e;
});
}

View File

@ -1,5 +1,5 @@
import moment from 'moment-timezone';
import prisma, { runQuery } from 'lib/db';
import prisma from 'lib/db';
import { subMinutes } from 'date-fns';
import { MYSQL, POSTGRESQL, MYSQL_DATE_FORMATS, POSTGRESQL_DATE_FORMATS } from 'lib/constants';
@ -15,7 +15,27 @@ export function getDatabase() {
return type;
}
export function getDateQuery(db, field, unit, timezone) {
export async function runQuery(query) {
return query.catch(e => {
throw e;
});
}
export async function rawQuery(query, ...params) {
const db = getDatabase();
if (db !== POSTGRESQL && db !== MYSQL) {
return Promise.reject(new Error('Unknown database.'));
}
const sql = db === MYSQL ? query.replace(/\$[0-9]+/g, '?') : query;
return prisma.$queryRaw.apply(prisma, [sql, ...params]);
}
export function getDateQuery(field, unit, timezone) {
const db = getDatabase();
if (db === POSTGRESQL) {
if (timezone) {
return `to_char(date_trunc('${unit}', ${field} at time zone '${timezone}'), '${POSTGRESQL_DATE_FORMATS[unit]}')`;
@ -34,6 +54,18 @@ export function getDateQuery(db, field, unit, timezone) {
}
}
export function getTimestampInterval(field) {
const db = getDatabase();
if (db === POSTGRESQL) {
return `floor(extract(epoch from max(${field}) - min(${field})))`;
}
if (db === MYSQL) {
return `floor(unix_timestamp(max(${field})) - unix_timestamp(min(${field})))`;
}
}
export async function getWebsiteById(website_id) {
return runQuery(
prisma.website.findOne({
@ -254,11 +286,7 @@ export async function createAccount(data) {
}
export function getMetrics(website_id, start_at, end_at) {
const db = getDatabase();
if (db === POSTGRESQL) {
return runQuery(
prisma.$queryRaw(
return rawQuery(
`
select sum(t.c) as "pageviews",
count(distinct t.session_id) as "uniques",
@ -266,9 +294,9 @@ export function getMetrics(website_id, start_at, end_at) {
sum(t.time) as "totaltime"
from (
select session_id,
${getDateQuery(db, 'created_at', 'hour')},
${getDateQuery('created_at', 'hour')},
count(*) c,
floor(extract(epoch from max(created_at) - min(created_at))) as "time"
${getTimestampInterval('created_at')} as "time"
from pageview
where website_id=$1
and created_at between $2 and $3
@ -278,39 +306,9 @@ export function getMetrics(website_id, start_at, end_at) {
website_id,
start_at,
end_at,
),
);
}
if (db === MYSQL) {
return runQuery(
prisma.$queryRaw(
`
select sum(t.c) as "pageviews",
count(distinct t.session_id) as "uniques",
sum(case when t.c = 1 then 1 else 0 end) as "bounces",
sum(t.time) as "totaltime"
from (
select session_id,
${getDateQuery(db, 'created_at', 'hour')},
count(*) c,
floor(unix_timestamp(max(created_at)) - unix_timestamp(min(created_at))) as "time"
from pageview
where website_id=?
and created_at between ? and ?
group by 1, 2
) t
`,
website_id,
start_at,
end_at,
),
);
}
return Promise.reject(new Error('Unknown database.'));
}
export function getPageviews(
website_id,
start_at,
@ -319,13 +317,9 @@ export function getPageviews(
unit = 'day',
count = '*',
) {
const db = getDatabase();
if (db === POSTGRESQL) {
return runQuery(
prisma.$queryRaw(
return rawQuery(
`
select ${getDateQuery(db, 'created_at', unit, timezone)} t,
select ${getDateQuery('created_at', unit, timezone)} t,
count(${count}) y
from pageview
where website_id=$1
@ -336,40 +330,13 @@ export function getPageviews(
website_id,
start_at,
end_at,
),
);
}
if (db === MYSQL) {
return runQuery(
prisma.$queryRaw(
`
select ${getDateQuery(db, 'created_at', unit, timezone)} t,
count(${count}) y
from pageview
where website_id=?
and created_at between ? and ?
group by 1
order by 1
`,
website_id,
start_at,
end_at,
),
);
}
return Promise.reject(new Error('Unknown database.'));
}
export function getRankings(website_id, start_at, end_at, type, table, domain) {
const db = getDatabase();
const filter = domain ? `and ${type} not like '%${domain}%'` : '';
if (db === POSTGRESQL) {
return runQuery(
prisma.$queryRaw(
return rawQuery(
`
select distinct ${type} x, count(*) y
from ${table}
@ -382,39 +349,13 @@ export function getRankings(website_id, start_at, end_at, type, table, domain) {
website_id,
start_at,
end_at,
),
);
}
if (db === MYSQL) {
return runQuery(
prisma.$queryRaw(
`
select distinct ${type} x, count(*) y
from ${table}
where website_id=?
and created_at between ? and ?
${filter}
group by 1
order by 2 desc
`,
website_id,
start_at,
end_at,
),
);
}
return Promise.reject(new Error('Unknown database.'));
}
export function getActiveVisitors(website_id) {
const db = getDatabase();
const date = subMinutes(new Date(), 5);
if (db === POSTGRESQL) {
return runQuery(
prisma.$queryRaw(
return rawQuery(
`
select count(distinct session_id) x
from pageview
@ -423,38 +364,15 @@ export function getActiveVisitors(website_id) {
`,
website_id,
date,
),
);
}
if (db === MYSQL) {
return runQuery(
prisma.$queryRaw(
`
select count(distinct session_id) x
from pageview
where website_id=?
and created_at >= ?
`,
website_id,
date,
),
);
}
return Promise.reject(new Error('Unknown database.'));
}
export function getEvents(website_id, start_at, end_at, timezone = 'utc', unit = 'day') {
const db = getDatabase();
if (db === POSTGRESQL) {
return runQuery(
prisma.$queryRaw(
return rawQuery(
`
select
event_value x,
${getDateQuery(db, 'created_at', unit, timezone)} t,
${getDateQuery('created_at', unit, timezone)} t,
count(*) y
from event
where website_id=$1
@ -465,30 +383,5 @@ export function getEvents(website_id, start_at, end_at, timezone = 'utc', unit =
website_id,
start_at,
end_at,
),
);
}
if (db === MYSQL) {
return runQuery(
prisma.$queryRaw(
`
select
event_value x,
${getDateQuery(db, 'created_at', unit, timezone)} t,
count(*) y
from event
where website_id=?
and created_at between ? and ?
group by 1, 2
order by 2
`,
website_id,
start_at,
end_at,
),
);
}
return Promise.reject(new Error('Unknown database.'));
}