diff --git a/apps/api/src/controllers/export.controller.ts b/apps/api/src/controllers/export.controller.ts old mode 100644 new mode 100755 index 15b045c03..86f279a71 --- a/apps/api/src/controllers/export.controller.ts +++ b/apps/api/src/controllers/export.controller.ts @@ -60,6 +60,14 @@ async function getProjectId( return projectId; } +const preprocessCommaSeparatedArray = (arg: unknown) => { + if (arg == null) return undefined; + if (Array.isArray(arg)) return arg; + if (typeof arg === 'string') + return arg.split(',').map((s) => s.trim()).filter(Boolean); + return arg; +}; + export const eventsScheme = z.object({ project_id: z.string().optional(), projectId: z.string().optional(), @@ -83,24 +91,8 @@ export const eventsScheme = z.object({ return value; }, z.array(zChartEventFilter)) .optional(), - includes: z - .preprocess( - (arg) => { - if (arg == null) { - return undefined; - } - if (Array.isArray(arg)) { - return arg; - } - if (typeof arg === 'string') { - const parts = arg.split(',').map((s) => s.trim()).filter(Boolean); - return parts; - } - return arg; - }, - z.array(z.string()) - ) - .optional(), + includes: z.preprocess(preprocessCommaSeparatedArray, z.array(z.string())).optional(), + property_keys: z.preprocess(preprocessCommaSeparatedArray, z.array(z.string())).optional(), }); export async function events( @@ -110,7 +102,7 @@ export async function events( reply: FastifyReply ) { const projectId = await getProjectId(request); - const { limit, page: rawPage, event, start, end, profileId, includes, filters } = request.query; + const { limit, page: rawPage, event, start, end, profileId, includes, filters, property_keys } = request.query; const take = Math.max(Math.min(limit, 1000), 1); const cursor = Math.max(rawPage, 1) - 1; const options: GetEventListOptions = { @@ -122,9 +114,11 @@ export async function events( take, profileId, filters, + propertyKeys: property_keys, select: { profile: false, meta: false, + properties: true, ...includes?.reduce((acc, key) => ({ ...acc, [key]: true }), {}), }, }; diff --git a/packages/db/src/services/event.service.ts b/packages/db/src/services/event.service.ts old mode 100644 new mode 100755 index 4a393c4d7..788905372 --- a/packages/db/src/services/event.service.ts +++ b/packages/db/src/services/event.service.ts @@ -466,6 +466,7 @@ export interface GetEventListOptions { select?: SelectHelper; custom?: (sb: SqlBuilderObject) => void; dateIntervalInDays?: number; + propertyKeys?: string[]; } export async function getEventList(options: GetEventListOptions) { @@ -484,6 +485,7 @@ export async function getEventList(options: GetEventListOptions) { custom, select: incomingSelect, dateIntervalInDays = 0.5, + propertyKeys, } = options; const { sb, getSql, join } = createSqlBuilder(); @@ -548,7 +550,12 @@ export async function getEventList(options: GetEventListOptions) { sb.select.sessionId = 'session_id'; } if (select.properties) { - sb.select.properties = 'properties'; + if (propertyKeys && propertyKeys.length > 0) { + const keys = [...new Set(propertyKeys)].map((k) => sqlstring.escape(k)).join(', '); + sb.select.properties = `mapFilter((k, v) -> k IN (${keys}), properties) AS properties`; + } else { + sb.select.properties = 'properties'; + } } if (select.country) { sb.select.country = 'country';