Merge getBySku into single SQL query with FOR JSON sub-queries
Replaces 6 round-trips (1 sequential resolve + 5 parallel detail) with one query. Auth resolution, article detail, categories, photos, eans, and prices are all fetched in a single round-trip.
This commit is contained in:
@@ -1,22 +1,70 @@
|
||||
import resolveArticleBySku from './resolveArticleBySku.js';
|
||||
import queryBySku from './queryBySku.js';
|
||||
import { GET_ARTICLE_BY_SKU_FULL } from '../../sql/article.js';
|
||||
|
||||
function parseJsonArray(raw) {
|
||||
if (!raw) return [];
|
||||
const arr = typeof raw === 'string' ? JSON.parse(raw) : raw;
|
||||
return Array.isArray(arr) ? arr : [];
|
||||
}
|
||||
|
||||
export default function getBySku(pool) {
|
||||
const resolve = resolveArticleBySku(pool);
|
||||
const load = queryBySku(pool);
|
||||
|
||||
return async (googleAuthId, sku) => {
|
||||
let t0 = performance.now();
|
||||
const { articleId, languageId } = await resolve(googleAuthId, sku);
|
||||
console.log(`[getBySku] resolveArticleBySku ${(performance.now() - t0).toFixed(1)}ms`);
|
||||
const t0 = performance.now();
|
||||
const result = await pool
|
||||
.request()
|
||||
.input('sku', sku)
|
||||
.input('googleAuthId', googleAuthId)
|
||||
.query(GET_ARTICLE_BY_SKU_FULL);
|
||||
console.log(`[getBySku] single query ${(performance.now() - t0).toFixed(1)}ms`);
|
||||
|
||||
t0 = performance.now();
|
||||
const article = await load(articleId, languageId);
|
||||
console.log(`[getBySku] queryBySku (parallel) ${(performance.now() - t0).toFixed(1)}ms`);
|
||||
if (!article) {
|
||||
const row = result.recordset[0];
|
||||
if (!row) {
|
||||
throw new Error('Article not found');
|
||||
}
|
||||
if (!row.articleId || !row.categoryId) {
|
||||
throw new Error('Article not found');
|
||||
}
|
||||
if (!row.companyId || !row.rootCategoryId || !row.languageId) {
|
||||
throw new Error('Parent not found');
|
||||
}
|
||||
if (!row.companyuserId) {
|
||||
throw new Error('Not authorized');
|
||||
}
|
||||
|
||||
return article;
|
||||
const a = typeof row.articleJson === 'string' ? JSON.parse(row.articleJson) : row.articleJson;
|
||||
|
||||
return {
|
||||
article: {
|
||||
id: a.id,
|
||||
sku: a.sku,
|
||||
name: a.name,
|
||||
slug: a.slug,
|
||||
unitamount: a.unitamount,
|
||||
weight: a.weight,
|
||||
unit: {
|
||||
si: a.unitSi,
|
||||
basesi: a.unitBasesi,
|
||||
basesifactor: a.unitBasesifactor,
|
||||
symbol: a.unitSymbol ?? null,
|
||||
name: a.unitName ?? null,
|
||||
},
|
||||
brand: a.brandName
|
||||
? {
|
||||
name: a.brandName,
|
||||
thumbW: a.brandThumbW,
|
||||
thumbH: a.brandThumbH,
|
||||
thumbHash: a.brandThumbHash,
|
||||
}
|
||||
: null,
|
||||
categoryIds: parseJsonArray(a.categoryIdsJson).map((r) => r.category_id),
|
||||
photos: parseJsonArray(a.photosJson),
|
||||
eans: parseJsonArray(a.eansJson).map((r) => r.ean),
|
||||
prices: parseJsonArray(a.pricesJson),
|
||||
optionsCount: a.optionsCount,
|
||||
articleListCount: a.articleListCount,
|
||||
childCount: a.childCount,
|
||||
fatherArticleId: a.fatherArticleId,
|
||||
fatherSku: a.fatherSku,
|
||||
},
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user