fetch collections from new table (#179)

* fetch collections from new table

* optimization fixes

* fixed fields
This commit is contained in:
Arwid Thornström
2025-10-09 12:59:32 +02:00
committed by GitHub
parent a6097b0750
commit 3259fa702c
+43 -22
View File
@@ -27,8 +27,12 @@ export class CollectionAPI extends BaseSQLDataSource {
SELECT SELECT
id, id,
name, name,
metadata metadata,
FROM editorial_pages (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 WHERE type = 'collection' AND deleted IS NULL
ORDER BY name ORDER BY name
`; `;
@@ -47,8 +51,12 @@ export class CollectionAPI extends BaseSQLDataSource {
SELECT SELECT
id, id,
name, name,
metadata metadata,
FROM editorial_pages (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 WHERE id = ? AND type = 'collection' AND deleted IS NULL
`; `;
const collection = await this.knex.raw(query, [id]).then((data) => { const collection = await this.knex.raw(query, [id]).then((data) => {
@@ -61,12 +69,9 @@ export class CollectionAPI extends BaseSQLDataSource {
} }
createCollectionFromRow(row: any): Collection { createCollectionFromRow(row: any): Collection {
let productIds: number[] = []; const productIds: number[] = Array.isArray(row.product_ids)
if (row.metadata && Array.isArray(row.metadata.collection_products)) { ? row.product_ids
productIds = row.metadata.collection_products.map((id: string | number) => : [];
Number(id),
);
}
return { return {
id: row.id, id: row.id,
name: row.name, name: row.name,
@@ -85,35 +90,51 @@ export class CollectionAPI extends BaseSQLDataSource {
private async batchGetProductCollections( private async batchGetProductCollections(
productIds: readonly number[], productIds: readonly number[],
): Promise<Collection[][]> { ): Promise<Collection[][]> {
const productIdsStr = productIds.map(String); const productIdsInt = productIds.map(Number);
const query = ` const query = `
WITH collection_products AS ( WITH collection_products AS (
SELECT SELECT
e.id, e.id,
e.name, e.name,
e.metadata, 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 FROM editorial_pages e
JOIN editorial_collection_products ecp ON ecp.editorial_page_id = e.id
WHERE e.type = 'collection' WHERE e.type = 'collection'
AND e.deleted IS NULL 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 SELECT
WHERE product_id = ANY (?) 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 // Group collections by product ID
const collectionsByProduct: { [key: string]: Collection[] } = {}; const collectionsByProduct: { [key: string]: Collection[] } = {};
productIdsStr.forEach((id) => { productIdsInt.forEach((id) => {
collectionsByProduct[id] = []; collectionsByProduct[id] = [];
}); });
results.rows.forEach((row) => { results.rows.forEach((row) => {
const productId = row.product_id; const collection = this.createCollectionFromRow(row);
if (!collectionsByProduct[productId]) // Add this collection to each product ID that it contains
collectionsByProduct[productId] = []; const collectionProductIds = row.product_ids || [];
collectionsByProduct[productId].push(this.createCollectionFromRow(row)); 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 collections in the same order as the input productIds
return productIdsStr.map((id) => collectionsByProduct[id] || []); return productIdsInt.map((id) => collectionsByProduct[id] || []);
} }
} }