From 3259fa702c36c62b94c12d38fda146edc7df64a5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Arwid=20Thornstr=C3=B6m?= Date: Thu, 9 Oct 2025 12:59:32 +0200 Subject: [PATCH] fetch collections from new table (#179) * fetch collections from new table * optimization fixes * fixed fields --- src/datasources/collection-api.ts | 75 ++++++++++++++++++++----------- 1 file changed, 48 insertions(+), 27 deletions(-) diff --git a/src/datasources/collection-api.ts b/src/datasources/collection-api.ts index abd0534..7127d03 100644 --- a/src/datasources/collection-api.ts +++ b/src/datasources/collection-api.ts @@ -24,11 +24,15 @@ export class CollectionAPI extends BaseSQLDataSource { Scopes.PRODUCTS_PUBLIC_READ, ]); const query = ` - SELECT - id, + SELECT + id, name, - metadata - FROM editorial_pages + metadata, + (SELECT array_agg(DISTINCT ecp.product_id) + FROM editorial_collection_products ecp + WHERE ecp.editorial_page_id = ep.id + ) AS product_ids + FROM editorial_pages ep WHERE type = 'collection' AND deleted IS NULL ORDER BY name `; @@ -44,11 +48,15 @@ export class CollectionAPI extends BaseSQLDataSource { Scopes.PRODUCTS_PUBLIC_READ, ]); const query = ` - SELECT - id, + SELECT + id, name, - metadata - FROM editorial_pages + metadata, + (SELECT array_agg(DISTINCT ecp.product_id) + FROM editorial_collection_products ecp + WHERE ecp.editorial_page_id = ep.id + ) AS product_ids + FROM editorial_pages ep WHERE id = ? AND type = 'collection' AND deleted IS NULL `; const collection = await this.knex.raw(query, [id]).then((data) => { @@ -61,12 +69,9 @@ export class CollectionAPI extends BaseSQLDataSource { } createCollectionFromRow(row: any): Collection { - let productIds: number[] = []; - if (row.metadata && Array.isArray(row.metadata.collection_products)) { - productIds = row.metadata.collection_products.map((id: string | number) => - Number(id), - ); - } + const productIds: number[] = Array.isArray(row.product_ids) + ? row.product_ids + : []; return { id: row.id, name: row.name, @@ -85,35 +90,51 @@ export class CollectionAPI extends BaseSQLDataSource { private async batchGetProductCollections( productIds: readonly number[], ): Promise { - const productIdsStr = productIds.map(String); + const productIdsInt = productIds.map(Number); const query = ` WITH collection_products AS ( - SELECT + SELECT e.id, e.name, e.metadata, - jsonb_array_elements_text(e.metadata->'collection_products') AS product_id + array_agg(DISTINCT ecp.product_id) AS product_ids FROM editorial_pages e + JOIN editorial_collection_products ecp ON ecp.editorial_page_id = e.id WHERE e.type = 'collection' AND e.deleted IS NULL - AND e.metadata->'collection_products' IS NOT NULL + GROUP BY e.id, e.name, e.metadata ) - SELECT * FROM collection_products - WHERE product_id = ANY (?) + SELECT + id, + name, + metadata, + product_ids + FROM collection_products + WHERE product_ids && ?::integer[]; `; - const results = await this.knex.raw(query, [productIdsStr]); + const results = await this.knex.raw(query, [productIdsInt]); + // Group collections by product ID const collectionsByProduct: { [key: string]: Collection[] } = {}; - productIdsStr.forEach((id) => { + productIdsInt.forEach((id) => { collectionsByProduct[id] = []; }); + results.rows.forEach((row) => { - const productId = row.product_id; - if (!collectionsByProduct[productId]) - collectionsByProduct[productId] = []; - collectionsByProduct[productId].push(this.createCollectionFromRow(row)); + const collection = this.createCollectionFromRow(row); + // Add this collection to each product ID that it contains + const collectionProductIds = row.product_ids || []; + collectionProductIds.forEach((productId: number) => { + if (productIdsInt.includes(productId)) { + if (!collectionsByProduct[productId]) { + collectionsByProduct[productId] = []; + } + collectionsByProduct[productId].push(collection); + } + }); }); + // Return collections in the same order as the input productIds - return productIdsStr.map((id) => collectionsByProduct[id] || []); + return productIdsInt.map((id) => collectionsByProduct[id] || []); } }