Merge pull request #1563 from umami-software/feat/um-66-update-clickhouse-schema-uuid

Feat/um 66 update clickhouse schema UUID
This commit is contained in:
Mike Cao 2022-10-11 21:46:16 -07:00 committed by GitHub
commit 9a90d2e88f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 147 additions and 96 deletions

View File

@ -17,8 +17,8 @@ export default function WebsiteHeader({ websiteId, title, domain, showLink = fal
<Favicon domain={domain} /> <Favicon domain={domain} />
<Link <Link
className={styles.titleLink} className={styles.titleLink}
href="/website/[...id]" href="/websites/[...id]"
as={`/website/${websiteId}/${title}`} as={`/websites/${websiteId}/${title}`}
> >
<OverflowText tooltipId={`${websiteId}-title`}>{title}</OverflowText> <OverflowText tooltipId={`${websiteId}-title`}>{title}</OverflowText>
</Link> </Link>
@ -41,8 +41,8 @@ export default function WebsiteHeader({ websiteId, title, domain, showLink = fal
<RefreshButton websiteId={websiteId} /> <RefreshButton websiteId={websiteId} />
{showLink && ( {showLink && (
<Link <Link
href="/website/[...id]" href="/websites/[...id]"
as={`/website/${websiteId}/${title}`} as={`/websites/${websiteId}/${title}`}
className={styles.link} className={styles.link}
icon={<Arrow />} icon={<Arrow />}
size="small" size="small"

View File

@ -27,7 +27,7 @@ export default function WebsiteList({ websites, showCharts, limit }) {
const ordered = useMemo( const ordered = useMemo(
() => () =>
websites websites
.map(website => ({ ...website, order: websiteOrder.indexOf(website.id) || 0 })) .map(website => ({ ...website, order: websiteOrder.indexOf(website.websiteUuid) || 0 }))
.sort(firstBy('order')), .sort(firstBy('order')),
[websites, websiteOrder], [websites, websiteOrder],
); );
@ -46,11 +46,11 @@ export default function WebsiteList({ websites, showCharts, limit }) {
return ( return (
<div> <div>
{ordered.map(({ id, name, domain }, index) => {ordered.map(({ websiteUuid, name, domain }, index) =>
index < limit ? ( index < limit ? (
<div key={id} className={styles.website}> <div key={websiteUuid} className={styles.website}>
<WebsiteChart <WebsiteChart
websiteId={id} websiteId={websiteUuid}
title={name} title={name}
domain={domain} domain={domain}
showChart={showCharts} showChart={showCharts}

View File

@ -46,7 +46,7 @@ export default function WebsiteSettings() {
icon={<LinkIcon />} icon={<LinkIcon />}
size="small" size="small"
tooltip={<FormattedMessage id="message.get-share-url" defaultMessage="Get share URL" />} tooltip={<FormattedMessage id="message.get-share-url" defaultMessage="Get share URL" />}
tooltipId={`button-share-${row.id}`} tooltipId={`button-share-${row.websiteUuid}`}
onClick={() => setShowUrl(row)} onClick={() => setShowUrl(row)}
/> />
)} )}
@ -56,42 +56,46 @@ export default function WebsiteSettings() {
tooltip={ tooltip={
<FormattedMessage id="message.get-tracking-code" defaultMessage="Get tracking code" /> <FormattedMessage id="message.get-tracking-code" defaultMessage="Get tracking code" />
} }
tooltipId={`button-code-${row.id}`} tooltipId={`button-code-${row.websiteUuid}`}
onClick={() => setShowCode(row)} onClick={() => setShowCode(row)}
/> />
<Button <Button
icon={<Pen />} icon={<Pen />}
size="small" size="small"
tooltip={<FormattedMessage id="label.edit" defaultMessage="Edit" />} tooltip={<FormattedMessage id="label.edit" defaultMessage="Edit" />}
tooltipId={`button-edit-${row.id}`} tooltipId={`button-edit-${row.websiteUuid}`}
onClick={() => setEditWebsite(row)} onClick={() => setEditWebsite(row)}
/> />
<Button <Button
icon={<Reset />} icon={<Reset />}
size="small" size="small"
tooltip={<FormattedMessage id="label.reset" defaultMessage="Reset" />} tooltip={<FormattedMessage id="label.reset" defaultMessage="Reset" />}
tooltipId={`button-reset-${row.id}`} tooltipId={`button-reset-${row.websiteUuid}`}
onClick={() => setResetWebsite(row)} onClick={() => setResetWebsite(row)}
/> />
<Button <Button
icon={<Trash />} icon={<Trash />}
size="small" size="small"
tooltip={<FormattedMessage id="label.delete" defaultMessage="Delete" />} tooltip={<FormattedMessage id="label.delete" defaultMessage="Delete" />}
tooltipId={`button-delete-${row.id}`} tooltipId={`button-delete-${row.websiteUuid}`}
onClick={() => setDeleteWebsite(row)} onClick={() => setDeleteWebsite(row)}
/> />
</ButtonLayout> </ButtonLayout>
); );
const DetailsLink = ({ id, name, domain }) => ( const DetailsLink = ({ websiteUuid, name, domain }) => (
<Link className={styles.detailLink} href="/website/[...id]" as={`/website/${id}/${name}`}> <Link
className={styles.detailLink}
href="/websites/[...id]"
as={`/websites/${websiteUuid}/${name}`}
>
<Favicon domain={domain} /> <Favicon domain={domain} />
<OverflowText tooltipId={`${id}-name`}>{name}</OverflowText> <OverflowText tooltipId={`${websiteUuid}-name`}>{name}</OverflowText>
</Link> </Link>
); );
const Domain = ({ domain, id }) => ( const Domain = ({ domain, websiteUuid }) => (
<OverflowText tooltipId={`${id}-domain`}>{domain}</OverflowText> <OverflowText tooltipId={`${websiteUuid}-domain`}>{domain}</OverflowText>
); );
const adminColumns = [ const adminColumns = [
@ -199,7 +203,7 @@ export default function WebsiteSettings() {
title={<FormattedMessage id="label.reset-website" defaultMessage="Reset statistics" />} title={<FormattedMessage id="label.reset-website" defaultMessage="Reset statistics" />}
> >
<ResetForm <ResetForm
values={{ type: 'websites', id: resetWebsite.id, name: resetWebsite.name }} values={{ type: 'websites', id: resetWebsite.websiteUuid, name: resetWebsite.name }}
onSave={handleSave} onSave={handleSave}
onClose={handleClose} onClose={handleClose}
/> />
@ -210,7 +214,7 @@ export default function WebsiteSettings() {
title={<FormattedMessage id="label.delete-website" defaultMessage="Delete website" />} title={<FormattedMessage id="label.delete-website" defaultMessage="Delete website" />}
> >
<DeleteForm <DeleteForm
values={{ type: 'websites', id: deleteWebsite.id, name: deleteWebsite.name }} values={{ type: 'websites', id: deleteWebsite.websiteUuid, name: deleteWebsite.name }}
onSave={handleSave} onSave={handleSave}
onClose={handleClose} onClose={handleClose}
/> />

View File

@ -3,9 +3,9 @@ SET allow_experimental_object_type = 1;
-- Create Event -- Create Event
CREATE TABLE event CREATE TABLE event
( (
website_id UInt32, website_id UUID,
session_uuid UUID, session_id UUID,
event_uuid Nullable(UUID), event_id Nullable(UUID),
--session --session
hostname LowCardinality(String), hostname LowCardinality(String),
browser LowCardinality(String), browser LowCardinality(String),
@ -23,13 +23,13 @@ CREATE TABLE event
created_at DateTime('UTC') created_at DateTime('UTC')
) )
engine = MergeTree engine = MergeTree
ORDER BY (website_id, session_uuid, created_at) ORDER BY (website_id, session_id, created_at)
SETTINGS index_granularity = 8192; SETTINGS index_granularity = 8192;
CREATE TABLE event_queue ( CREATE TABLE event_queue (
website_id UInt32, website_id UUID,
session_uuid UUID, session_id UUID,
event_uuid Nullable(UUID), event_id Nullable(UUID),
url String, url String,
referrer String, referrer String,
hostname LowCardinality(String), hostname LowCardinality(String),
@ -44,7 +44,7 @@ CREATE TABLE event_queue (
created_at DateTime('UTC') created_at DateTime('UTC')
) )
ENGINE = Kafka ENGINE = Kafka
SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input broker list SETTINGS kafka_broker_list = 'dev-01.umami.dev:9092,dev-01.umami.dev:9093,dev-01.umami.dev:9094', -- input broker list
kafka_topic_list = 'event', kafka_topic_list = 'event',
kafka_group_name = 'event_consumer_group', kafka_group_name = 'event_consumer_group',
kafka_format = 'JSONEachRow', kafka_format = 'JSONEachRow',
@ -53,8 +53,8 @@ SETTINGS kafka_broker_list = 'domain:9092,domain:9093,domain:9094', -- input bro
CREATE MATERIALIZED VIEW event_queue_mv TO event AS CREATE MATERIALIZED VIEW event_queue_mv TO event AS
SELECT website_id, SELECT website_id,
session_uuid, session_id,
event_uuid, event_id,
url, url,
referrer, referrer,
hostname, hostname,

View File

@ -60,6 +60,10 @@ function getDateFormat(date) {
return `'${dateFormat(date, 'UTC:yyyy-mm-dd HH:MM:ss')}'`; return `'${dateFormat(date, 'UTC:yyyy-mm-dd HH:MM:ss')}'`;
} }
function getCommaSeparatedStringFormat(data) {
return data.map(a => `'${a}'`).join(',');
}
function getBetweenDates(field, start_at, end_at) { function getBetweenDates(field, start_at, end_at) {
return `${field} between ${getDateFormat(start_at)} return `${field} between ${getDateFormat(start_at)}
and ${getDateFormat(end_at)}`; and ${getDateFormat(end_at)}`;
@ -180,6 +184,7 @@ export default {
getDateStringQuery, getDateStringQuery,
getDateQuery, getDateQuery,
getDateFormat, getDateFormat,
getCommaSeparatedStringFormat,
getBetweenDates, getBetweenDates,
getFilterQuery, getFilterQuery,
parseFilters, parseFilters,

View File

@ -11,9 +11,7 @@ export default async (req, res) => {
return unauthorized(res); return unauthorized(res);
} }
const { id } = req.query; const { id: websiteId } = req.query;
const websiteId = +id;
const result = await getActiveVisitors(websiteId); const result = await getActiveVisitors(websiteId);

View File

@ -14,13 +14,11 @@ export default async (req, res) => {
return unauthorized(res); return unauthorized(res);
} }
const { id, start_at, end_at, unit, tz, url, event_name } = req.query; const { id: websiteId, start_at, end_at, unit, tz, url, event_name } = req.query;
if (!moment.tz.zone(tz) || !unitTypes.includes(unit)) { if (!moment.tz.zone(tz) || !unitTypes.includes(unit)) {
return badRequest(res); return badRequest(res);
} }
const websiteId = +id;
const startDate = new Date(+start_at); const startDate = new Date(+start_at);
const endDate = new Date(+end_at); const endDate = new Date(+end_at);

View File

@ -1,14 +1,10 @@
import { methodNotAllowed, ok, unauthorized, getRandomChars } from 'next-basics';
import { deleteWebsite, getAccount, getWebsite, updateWebsite } from 'queries';
import { allowQuery } from 'lib/auth'; import { allowQuery } from 'lib/auth';
import { useAuth, useCors } from 'lib/middleware'; import { useAuth, useCors } from 'lib/middleware';
import { validate } from 'uuid'; import { getRandomChars, methodNotAllowed, ok, unauthorized } from 'next-basics';
import { deleteWebsite, getAccount, getWebsite, getWebsiteByUuid, updateWebsite } from 'queries';
export default async (req, res) => { export default async (req, res) => {
const { id } = req.query; const { id: websiteId } = req.query;
const websiteId = +id;
const where = validate(id) ? { websiteUuid: id } : { id: +id };
if (req.method === 'GET') { if (req.method === 'GET') {
await useCors(req, res); await useCors(req, res);
@ -17,7 +13,7 @@ export default async (req, res) => {
return unauthorized(res); return unauthorized(res);
} }
const website = await getWebsite(where); const website = await getWebsiteByUuid(websiteId);
return ok(res, website); return ok(res, website);
} }
@ -33,7 +29,7 @@ export default async (req, res) => {
account = await getAccount({ accountUuid }); account = await getAccount({ accountUuid });
} }
const website = await getWebsite(where); const website = await getWebsite(websiteId);
const shareId = enable_share_url ? website.shareId || getRandomChars(8) : null; const shareId = enable_share_url ? website.shareId || getRandomChars(8) : null;
@ -48,7 +44,7 @@ export default async (req, res) => {
shareId: shareId, shareId: shareId,
userId: account ? account.id : +owner, userId: account ? account.id : +owner,
}, },
where, { websiteUuid: websiteId },
); );
return ok(res); return ok(res);

View File

@ -1,8 +1,8 @@
import { getPageviewMetrics, getSessionMetrics, getWebsiteById } from 'queries';
import { ok, methodNotAllowed, unauthorized, badRequest } from 'next-basics';
import { allowQuery } from 'lib/auth'; import { allowQuery } from 'lib/auth';
import { useCors } from 'lib/middleware';
import { FILTER_IGNORED } from 'lib/constants'; import { FILTER_IGNORED } from 'lib/constants';
import { useCors } from 'lib/middleware';
import { badRequest, methodNotAllowed, ok, unauthorized } from 'next-basics';
import { getPageviewMetrics, getSessionMetrics, getWebsiteByUuid } from 'queries';
const sessionColumns = ['browser', 'os', 'device', 'screen', 'country', 'language']; const sessionColumns = ['browser', 'os', 'device', 'screen', 'country', 'language'];
const pageviewColumns = ['url', 'referrer', 'query']; const pageviewColumns = ['url', 'referrer', 'query'];
@ -41,9 +41,19 @@ export default async (req, res) => {
return unauthorized(res); return unauthorized(res);
} }
const { id, type, start_at, end_at, url, referrer, os, browser, device, country } = req.query; const {
id: websiteId,
type,
start_at,
end_at,
url,
referrer,
os,
browser,
device,
country,
} = req.query;
const websiteId = +id;
const startDate = new Date(+start_at); const startDate = new Date(+start_at);
const endDate = new Date(+end_at); const endDate = new Date(+end_at);
@ -83,7 +93,7 @@ export default async (req, res) => {
let domain; let domain;
if (type === 'referrer') { if (type === 'referrer') {
const website = await getWebsiteById(websiteId); const website = await getWebsiteByUuid(websiteId);
if (!website) { if (!website) {
return badRequest(res); return badRequest(res);

View File

@ -14,10 +14,20 @@ export default async (req, res) => {
return unauthorized(res); return unauthorized(res);
} }
const { id, start_at, end_at, unit, tz, url, referrer, os, browser, device, country } = const {
req.query; id: websiteId,
start_at,
end_at,
unit,
tz,
url,
referrer,
os,
browser,
device,
country,
} = req.query;
const websiteId = +id;
const startDate = new Date(+start_at); const startDate = new Date(+start_at);
const endDate = new Date(+end_at); const endDate = new Date(+end_at);

View File

@ -3,8 +3,7 @@ import { methodNotAllowed, ok, unauthorized } from 'next-basics';
import { allowQuery } from 'lib/auth'; import { allowQuery } from 'lib/auth';
export default async (req, res) => { export default async (req, res) => {
const { id } = req.query; const { id: websiteId } = req.query;
const websiteId = +id;
if (req.method === 'POST') { if (req.method === 'POST') {
if (!(await allowQuery(req))) { if (!(await allowQuery(req))) {

View File

@ -11,9 +11,18 @@ export default async (req, res) => {
return unauthorized(res); return unauthorized(res);
} }
const { website_id, start_at, end_at, url, referrer, os, browser, device, country } = req.query; const {
id: websiteId,
start_at,
end_at,
url,
referrer,
os,
browser,
device,
country,
} = req.query;
const websiteId = +website_id;
const startDate = new Date(+start_at); const startDate = new Date(+start_at);
const endDate = new Date(+end_at); const endDate = new Date(+end_at);

View File

@ -1,27 +1,27 @@
import prisma from 'lib/prisma'; import prisma from 'lib/prisma';
import redis, { DELETED } from 'lib/redis'; import redis, { DELETED } from 'lib/redis';
import { getWebsiteById } from 'queries'; import { getWebsiteByUuid } from 'queries';
export async function deleteWebsite(websiteId) { export async function deleteWebsite(websiteId) {
const { client, transaction } = prisma; const { client, transaction } = prisma;
const { websiteUuid } = await getWebsiteById(websiteId); const { websiteUuid } = await getWebsiteByUuid(websiteId);
return transaction([ return transaction([
client.pageview.deleteMany({ client.pageview.deleteMany({
where: { session: { website: { id: websiteId } } }, where: { session: { website: { websiteUuid: websiteId } } },
}), }),
client.eventData.deleteMany({ client.eventData.deleteMany({
where: { event: { session: { website: { id: websiteId } } } }, where: { event: { session: { website: { websiteUuid: websiteId } } } },
}), }),
client.event.deleteMany({ client.event.deleteMany({
where: { session: { website: { id: websiteId } } }, where: { session: { website: { websiteUuid: websiteId } } },
}), }),
client.session.deleteMany({ client.session.deleteMany({
where: { website: { id: websiteId } }, where: { website: { websiteUuid: websiteId } },
}), }),
client.website.delete({ client.website.delete({
where: { id: websiteId }, where: { websiteUuid: websiteId },
}), }),
]).then(async res => { ]).then(async res => {
if (redis.client) { if (redis.client) {

View File

@ -5,16 +5,16 @@ export async function resetWebsite(websiteId) {
return transaction([ return transaction([
client.pageview.deleteMany({ client.pageview.deleteMany({
where: { session: { website: { id: websiteId } } }, where: { session: { website: { websiteUuid: websiteId } } },
}), }),
client.eventData.deleteMany({ client.eventData.deleteMany({
where: { event: { session: { website: { id: websiteId } } } }, where: { event: { session: { website: { websiteUuid: websiteId } } } },
}), }),
client.event.deleteMany({ client.event.deleteMany({
where: { session: { website: { id: websiteId } } }, where: { session: { website: { websiteUuid: websiteId } } },
}), }),
client.session.deleteMany({ client.session.deleteMany({
where: { website: { id: websiteId } }, where: { website: { websiteUuid: websiteId } },
}), }),
]); ]);
} }

View File

@ -23,11 +23,13 @@ async function relationalQuery(
return rawQuery( return rawQuery(
`select `select
event_name x, event_name x,
${getDateQuery('created_at', unit, timezone)} t, ${getDateQuery('event.created_at', unit, timezone)} t,
count(*) y count(*) y
from event from event
where website_id=$1 join website
and created_at between $2 and $3 on event.website_id = website.website_id
where website_uuid='${websiteId}'
and event.created_at between $2 and $3
${getFilterQuery('event', filters, params)} ${getFilterQuery('event', filters, params)}
group by 1, 2 group by 1, 2
order by 2`, order by 2`,

View File

@ -25,19 +25,23 @@ function relationalQuery(websites, start_at) {
} }
function clickhouseQuery(websites, start_at) { function clickhouseQuery(websites, start_at) {
const { rawQuery, getDateFormat } = clickhouse; const { rawQuery, getDateFormat, getCommaSeparatedStringFormat } = clickhouse;
return rawQuery( return rawQuery(
`select `select
event_uuid, event_id,
website_id, website_id,
session_uuid, session_id,
created_at, created_at,
url, url,
event_name event_name
from event from event
where event_name != '' where event_name != ''
and ${websites && websites.length > 0 ? `website_id in (${websites.join(',')})` : '0 = 0'} and ${
websites && websites.length > 0
? `website_id in (${getCommaSeparatedStringFormat(websites)})`
: '0 = 0'
}
and created_at >= ${getDateFormat(start_at)}`, and created_at >= ${getDateFormat(start_at)}`,
); );
} }

View File

@ -38,8 +38,8 @@ async function clickhouseQuery(
const { getDateFormat, sendMessage } = kafka; const { getDateFormat, sendMessage } = kafka;
const params = { const params = {
session_uuid: sessionUuid, session_id: sessionUuid,
event_uuid: eventUuid, event_id: eventUuid,
website_id: websiteId, website_id: websiteId,
created_at: getDateFormat(new Date()), created_at: getDateFormat(new Date()),
url: url?.substring(0, URL_LENGTH), url: url?.substring(0, URL_LENGTH),

View File

@ -22,8 +22,9 @@ async function relationalQuery(websiteId, { startDate, endDate, column, table, f
return rawQuery( return rawQuery(
`select ${column} x, count(*) y `select ${column} x, count(*) y
from ${table} from ${table}
${` join website on ${table}.website_id = website.website_id`}
${joinSession} ${joinSession}
where ${table}.website_id=$1 where website.website_uuid='${websiteId}'
and ${table}.created_at between $2 and $3 and ${table}.created_at between $2 and $3
${pageviewQuery} ${pageviewQuery}
${joinSession && sessionQuery} ${joinSession && sessionQuery}

View File

@ -22,8 +22,9 @@ async function relationalQuery(websiteId, start_at, end_at, column, table, filte
`select url x, `select url x,
count(*) y count(*) y
from ${table} from ${table}
${` join website on ${table}.website_id = website.website_id`}
${joinSession} ${joinSession}
where ${table}.website_id=$1 where website.website_uuid='${websiteId}'
and ${table}.created_at between $2 and $3 and ${table}.created_at between $2 and $3
and ${table}.url like '%?%' and ${table}.url like '%?%'
${pageviewQuery} ${pageviewQuery}

View File

@ -34,8 +34,10 @@ async function relationalQuery(
`select ${getDateQuery('pageview.created_at', unit, timezone)} t, `select ${getDateQuery('pageview.created_at', unit, timezone)} t,
count(${count !== '*' ? `${count}${sessionKey}` : count}) y count(${count !== '*' ? `${count}${sessionKey}` : count}) y
from pageview from pageview
join website
on pageview.website_id = website.website_id
${joinSession} ${joinSession}
where pageview.website_id=$1 where website.website_uuid='${websiteId}'
and pageview.created_at between $2 and $3 and pageview.created_at between $2 and $3
${pageviewQuery} ${pageviewQuery}
${sessionQuery} ${sessionQuery}
@ -59,7 +61,7 @@ async function clickhouseQuery(
from from
(select (select
${getDateQuery('created_at', unit, timezone)} t, ${getDateQuery('created_at', unit, timezone)} t,
count(${count !== '*' ? 'distinct session_uuid' : count}) y count(${count !== '*' ? 'distinct session_id' : count}) y
from event from event
where event_name = '' where event_name = ''
and website_id= $1 and website_id= $1

View File

@ -25,15 +25,21 @@ async function relationalQuery(websites, start_at) {
} }
async function clickhouseQuery(websites, start_at) { async function clickhouseQuery(websites, start_at) {
const { getCommaSeparatedStringFormat } = clickhouse;
return clickhouse.rawQuery( return clickhouse.rawQuery(
`select `select
website_id, website_id,
session_uuid, session_id,
created_at, created_at,
url url
from event from event
where event_name = '' where event_name = ''
and ${websites && websites.length > 0 ? `website_id in (${websites.join(',')})` : '0 = 0'} and ${
websites && websites.length > 0
? `website_id in (${getCommaSeparatedStringFormat(websites)})`
: '0 = 0'
}
and created_at >= ${clickhouse.getDateFormat(start_at)}`, and created_at >= ${clickhouse.getDateFormat(start_at)}`,
); );
} }

View File

@ -20,8 +20,10 @@ async function relationalQuery(websiteId, { startDate, endDate, field, filters =
where x.session_id in ( where x.session_id in (
select pageview.session_id select pageview.session_id
from pageview from pageview
join website
on pageview.website_id = website.website_id
${joinSession} ${joinSession}
where pageview.website_id=$1 where website.website_uuid='${websiteId}'
and pageview.created_at between $2 and $3 and pageview.created_at between $2 and $3
${pageviewQuery} ${pageviewQuery}
${sessionQuery} ${sessionQuery}

View File

@ -17,8 +17,10 @@ async function relationalQuery(websiteId) {
return prisma.rawQuery( return prisma.rawQuery(
`select count(distinct session_id) x `select count(distinct session_id) x
from pageview from pageview
where website_id = $1 join website
and created_at >= $2`, on pageview.website_id = website.website_id
where website.website_uuid = '${websiteId}'
and pageview.created_at >= $2`,
params, params,
); );
} }
@ -28,7 +30,7 @@ async function clickhouseQuery(websiteId) {
const params = [websiteId]; const params = [websiteId];
return rawQuery( return rawQuery(
`select count(distinct session_uuid) x `select count(distinct session_id) x
from event from event
where website_id = $1 where website_id = $1
and created_at >= ${getDateFormat(subMinutes(new Date(), 5))}`, and created_at >= ${getDateFormat(subMinutes(new Date(), 5))}`,

View File

@ -30,11 +30,13 @@ async function relationalQuery(websiteId, { start_at, end_at, filters = {} }) {
count(*) c, count(*) c,
${getTimestampInterval('pageview.created_at')} as "time" ${getTimestampInterval('pageview.created_at')} as "time"
from pageview from pageview
join website
on pageview.website_id = website.website_id
${joinSession} ${joinSession}
where pageview.website_id=$1 where website.website_uuid='${websiteId}'
and pageview.created_at between $2 and $3 and pageview.created_at between $2 and $3
${pageviewQuery} ${pageviewQuery}
${sessionQuery} ${sessionQuery}
group by 1, 2 group by 1, 2
) t`, ) t`,
params, params,
@ -49,11 +51,11 @@ async function clickhouseQuery(websiteId, { start_at, end_at, filters = {} }) {
return rawQuery( return rawQuery(
`select `select
sum(t.c) as "pageviews", sum(t.c) as "pageviews",
count(distinct t.session_uuid) as "uniques", count(distinct t.session_id) as "uniques",
sum(if(t.c = 1, 1, 0)) as "bounces", sum(if(t.c = 1, 1, 0)) as "bounces",
sum(if(max_time < min_time + interval 1 hour, max_time-min_time, 0)) as "totaltime" sum(if(max_time < min_time + interval 1 hour, max_time-min_time, 0)) as "totaltime"
from ( from (
select session_uuid, select session_id,
${getDateQuery('created_at', 'day')} time_series, ${getDateQuery('created_at', 'day')} time_series,
count(*) c, count(*) c,
min(created_at) min_time, min(created_at) min_time,
@ -64,7 +66,7 @@ async function clickhouseQuery(websiteId, { start_at, end_at, filters = {} }) {
and ${getBetweenDates('created_at', start_at, end_at)} and ${getBetweenDates('created_at', start_at, end_at)}
${pageviewQuery} ${pageviewQuery}
${sessionQuery} ${sessionQuery}
group by session_uuid, time_series group by session_id, time_series
) t;`, ) t;`,
params, params,
); );