This commit is contained in:
Carl-Gerhard Lindesvärd
2024-07-24 00:41:53 +02:00
parent 8025859b6d
commit 2613a88c63
2 changed files with 36 additions and 19 deletions

View File

@@ -110,8 +110,11 @@ export async function chQuery<T extends Record<string, any>>(
return (await chQueryWithMeta<T>(query)).data; return (await chQueryWithMeta<T>(query)).data;
} }
export function formatClickhouseDate(_date: Date | string) { export function formatClickhouseDate(_date: Date | string, skipTime = false) {
const date = typeof _date === 'string' ? new Date(_date) : _date; const date = typeof _date === 'string' ? new Date(_date) : _date;
if (skipTime) {
return date.toISOString().split('T')[0];
}
return date.toISOString().replace('T', ' ').replace(/Z+$/, ''); return date.toISOString().replace('T', ' ').replace(/Z+$/, '');
} }

View File

@@ -9,6 +9,19 @@ import type {
import { formatClickhouseDate, TABLE_NAMES } from '../clickhouse-client'; import { formatClickhouseDate, TABLE_NAMES } from '../clickhouse-client';
import { createSqlBuilder } from '../sql-builder'; import { createSqlBuilder } from '../sql-builder';
function getPropertyKey(property: string) {
if (property.startsWith('properties.')) {
if (property.includes('*')) {
return `arrayMap(x -> trim(x), mapValues(mapExtractKeyLike(properties, ${escape(
property.replace(/^properties\./, '').replace('.*.', '.%.')
)})))`;
}
return `properties['${property.replace(/^properties\./, '')}']`;
}
return property;
}
export function getChartSql({ export function getChartSql({
event, event,
breakdowns, breakdowns,
@@ -55,18 +68,28 @@ export function getChartSql({
if (startDate) { if (startDate) {
sb.where.startDate = `created_at >= '${formatClickhouseDate(startDate)}'`; sb.where.startDate = `created_at >= '${formatClickhouseDate(startDate)}'`;
// if (interval === 'minute' || interval === 'hour') {
// sb.where.startDate = `created_at >= '${formatClickhouseDate(startDate)}'`;
// } else {
// sb.where.startDate = `toDate(created_at) >= '${formatClickhouseDate(startDate, true)}'`;
// }
} }
if (endDate) { if (endDate) {
sb.where.endDate = `created_at <= '${formatClickhouseDate(endDate)}'`; sb.where.endDate = `created_at <= '${formatClickhouseDate(endDate)}'`;
// if (interval === 'minute' || interval === 'hour') {
// sb.where.endDate = `created_at <= '${formatClickhouseDate(endDate)}'`;
// } else {
// sb.where.endDate = `toDate(created_at) <= '${formatClickhouseDate(endDate, true)}'`;
// }
} }
if (breakdowns.length > 0 && limit) { if (breakdowns.length > 0 && limit) {
sb.where.bar = `(${breakdowns.map((b) => b.name).join(',')}) IN ( sb.where.bar = `(${breakdowns.map((b) => getPropertyKey(b.name)).join(',')}) IN (
SELECT ${breakdowns.map((b) => b.name).join(',')} SELECT ${breakdowns.map((b) => getPropertyKey(b.name)).join(',')}
FROM ${TABLE_NAMES.events} FROM ${TABLE_NAMES.events}
${getWhere()} ${getWhere()}
GROUP BY ${breakdowns.map((b) => b.name).join(',')} GROUP BY ${breakdowns.map((b) => getPropertyKey(b.name)).join(',')}
ORDER BY count(*) DESC ORDER BY count(*) DESC
LIMIT ${limit} LIMIT ${limit}
)`; )`;
@@ -74,14 +97,7 @@ export function getChartSql({
breakdowns.forEach((breakdown, index) => { breakdowns.forEach((breakdown, index) => {
const key = `label_${index}`; const key = `label_${index}`;
const value = breakdown.name.startsWith('properties.') sb.select[key] = `${getPropertyKey(breakdown.name)} as ${key}`;
? `arrayMap(x -> trim(x), mapValues(mapExtractKeyLike(properties, ${escape(
breakdown.name.replace(/^properties\./, '').replace('.*.', '.%.')
)})))`
: escape(breakdown.name);
sb.select[key] = breakdown.name.startsWith('properties.')
? `arrayElement(${value}, 1) as ${key}`
: `${breakdown.name} as ${key}`;
sb.groupBy[key] = `${key}`; sb.groupBy[key] = `${key}`;
}); });
@@ -142,9 +158,7 @@ export function getEventFiltersWhereClause(filters: IChartEventFilter[]) {
.replace(/^properties\./, '') .replace(/^properties\./, '')
.replace('.*.', '.%.'); .replace('.*.', '.%.');
const isWildcard = propertyKey.includes('%'); const isWildcard = propertyKey.includes('%');
const whereFrom = `arrayMap(x -> trim(x), mapValues(mapExtractKeyLike(properties, ${escape( const whereFrom = getPropertyKey(name);
name.replace(/^properties\./, '').replace('.*.', '.%.')
)})))`;
switch (operator) { switch (operator) {
case 'is': { case 'is': {
@@ -153,7 +167,7 @@ export function getEventFiltersWhereClause(filters: IChartEventFilter[]) {
.map((val) => `x = ${escape(String(val).trim())}`) .map((val) => `x = ${escape(String(val).trim())}`)
.join(' OR ')}, ${whereFrom})`; .join(' OR ')}, ${whereFrom})`;
} else { } else {
where[id] = `properties['${propertyKey}'] IN (${value where[id] = `${whereFrom} IN (${value
.map((val) => escape(String(val).trim())) .map((val) => escape(String(val).trim()))
.join(', ')})`; .join(', ')})`;
} }
@@ -165,7 +179,7 @@ export function getEventFiltersWhereClause(filters: IChartEventFilter[]) {
.map((val) => `x != ${escape(String(val).trim())}`) .map((val) => `x != ${escape(String(val).trim())}`)
.join(' OR ')}, ${whereFrom})`; .join(' OR ')}, ${whereFrom})`;
} else { } else {
where[id] = `properties['${propertyKey}'] NOT IN (${value where[id] = `${whereFrom} NOT IN (${value
.map((val) => escape(String(val).trim())) .map((val) => escape(String(val).trim()))
.join(', ')})`; .join(', ')})`;
} }
@@ -180,7 +194,7 @@ export function getEventFiltersWhereClause(filters: IChartEventFilter[]) {
where[id] = value where[id] = value
.map( .map(
(val) => (val) =>
`properties['${propertyKey}'] LIKE ${escape(`%${String(val).trim()}%`)}` `${whereFrom} LIKE ${escape(`%${String(val).trim()}%`)}`
) )
.join(' OR '); .join(' OR ');
} }
@@ -195,7 +209,7 @@ export function getEventFiltersWhereClause(filters: IChartEventFilter[]) {
where[id] = value where[id] = value
.map( .map(
(val) => (val) =>
`properties['${propertyKey}'] NOT LIKE ${escape(`%${String(val).trim()}%`)}` `${whereFrom} NOT LIKE ${escape(`%${String(val).trim()}%`)}`
) )
.join(' OR '); .join(' OR ');
} }