[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)
|
||||
let searchArray = [{
|
||||
// Note: no `$skus(...)` join here — see the sku fetch below for why.
|
||||
let searchArray: any[] = [{
|
||||
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,
|
||||
facet_by: '',
|
||||
max_facet_values: 0,
|
||||
page: Math.floor(start / 20) + 1,
|
||||
sort_by: resolvedSort,
|
||||
include_fields: '$skus(*)',
|
||||
}];
|
||||
|
||||
// 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 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 "–"
|
||||
const formatPrice = (condition:string, skus: any) => {
|
||||
|
||||
Reference in New Issue
Block a user