[feat] boost card retrieval speed by removing typesense join
This commit is contained in:
@@ -129,15 +129,15 @@ const facetFilter = (facet:string) => {
|
|||||||
|
|
||||||
|
|
||||||
// primary search values (for cards)
|
// primary search values (for cards)
|
||||||
let searchArray = [{
|
// Note: no `$skus(...)` join here — see the sku fetch below for why.
|
||||||
|
let searchArray: any[] = [{
|
||||||
collection: 'cards',
|
collection: 'cards',
|
||||||
filter_by: `$skus(id:*) && sealed:false${languageFilter}${queryFilter ? ` && ${queryFilter}` : ''}${filterBy ? ` && ${filterBy}` : ''}`,
|
filter_by: `sealed:false${languageFilter}${queryFilter ? ` && ${queryFilter}` : ''}${filterBy ? ` && ${filterBy}` : ''}`,
|
||||||
per_page: 20,
|
per_page: 20,
|
||||||
facet_by: '',
|
facet_by: '',
|
||||||
max_facet_values: 0,
|
max_facet_values: 0,
|
||||||
page: Math.floor(start / 20) + 1,
|
page: Math.floor(start / 20) + 1,
|
||||||
sort_by: resolvedSort,
|
sort_by: resolvedSort,
|
||||||
include_fields: '$skus(*)',
|
|
||||||
}];
|
}];
|
||||||
|
|
||||||
// on first load (start === 0) we want to get the facets for the filters
|
// on first load (start === 0) we want to get the facets for the filters
|
||||||
@@ -172,6 +172,28 @@ const cardResults = searchResults.results[0] as any;
|
|||||||
const pokemon = cardResults.hits?.map((hit: any) => hit.document) ?? [];
|
const pokemon = cardResults.hits?.map((hit: any) => hit.document) ?? [];
|
||||||
const totalHits = cardResults?.found;
|
const totalHits = cardResults?.found;
|
||||||
|
|
||||||
|
// Skus aren't used for searching or sorting — they only supply the per-condition
|
||||||
|
// prices displayed on each card. Joining them into the primary search via
|
||||||
|
// `$skus(id:*)` forces Typesense to materialize the reverse join across the whole
|
||||||
|
// filtered result set before pagination (~20x slower). Instead, fetch skus for
|
||||||
|
// just the visible cards in one direct, indexed filter and attach them by id.
|
||||||
|
if (pokemon.length > 0) {
|
||||||
|
const cardIds = pokemon.map((c: any) => c.id);
|
||||||
|
const skuSearch = await client.collections('skus').documents().search({
|
||||||
|
q: '*',
|
||||||
|
query_by: 'condition',
|
||||||
|
filter_by: `card_id:=[${cardIds.map((id: string) => '`' + id + '`').join(',')}]`,
|
||||||
|
per_page: 250,
|
||||||
|
include_fields: 'condition,marketPrice,card_id',
|
||||||
|
});
|
||||||
|
const skusByCard: Record<string, any[]> = {};
|
||||||
|
for (const hit of (skuSearch.hits ?? []) as any[]) {
|
||||||
|
const sku = hit.document;
|
||||||
|
(skusByCard[sku.card_id] ??= []).push(sku);
|
||||||
|
}
|
||||||
|
for (const card of pokemon) card.skus = skusByCard[card.id] ?? [];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// format price to 2 decimal places (or 0 if price >=100) and adds a $ sign, if the price is null it returns "–"
|
// format price to 2 decimal places (or 0 if price >=100) and adds a $ sign, if the price is null it returns "–"
|
||||||
const formatPrice = (condition:string, skus: any) => {
|
const formatPrice = (condition:string, skus: any) => {
|
||||||
|
|||||||
Reference in New Issue
Block a user