diff --git a/src/pages/partials/cards.astro b/src/pages/partials/cards.astro index 446ca68..ca6bc0e 100644 --- a/src/pages/partials/cards.astro +++ b/src/pages/partials/cards.astro @@ -9,7 +9,7 @@ import * as util from 'util'; // all the facet fields we want to use for filtering const facetFields:any = { - "productLineName": "Product Line", + //"productLineName": "Product Line", "setName": "Set", "variant": "Variant", "rarityName": "Rarity", @@ -43,6 +43,22 @@ const languageFilter = language === 'en' ? " && productLineName:=`Pokemon`" : language === 'jp' ? " && productLineName:=`Pokemon Japan`" : ''; +// ── Query alias expansion ───────────────────────────────────────────────── +// Intercepts known shorthand queries that can't be handled by Typesense +// synonyms alone (e.g. terms that need to match across multiple set names) +// and rewrites them into a direct filter, clearing the query so it doesn't +// also try to text-match against card names. +const EREADER_SETS = ['Expedition Base Set', 'Aquapolis', 'Skyridge', 'Battle-e']; +const EREADER_RE = /^(e-?reader|e reader)$/i; + +let resolvedQuery = query; +let queryFilter = ''; + +if (EREADER_RE.test(query.trim())) { + resolvedQuery = ''; + queryFilter = `setName:=[${EREADER_SETS.map(s => '`' + s + '`').join(',')}]`; +} + const filters = Array.from(formData.entries()) .filter(([key]) => key !== 'q' && key !== 'start' && key !== 'sort' && key !== 'language') .reduce((acc, [key, value]) => { @@ -67,14 +83,14 @@ const facetFilter = (facet:string) => { .map(([field, values]) => `${field}:=[${values.map(v => '`'+v+'`').join(',')}]`) .join(' && '); // Language filter is always included so facet counts stay accurate - return `sealed:false${languageFilter}${otherFilters ? ` && ${otherFilters}` : ''}`; + return `sealed:false${languageFilter}${queryFilter ? ` && ${queryFilter}` : ''}${otherFilters ? ` && ${otherFilters}` : ''}`; }; // primary search values (for cards) let searchArray = [{ collection: 'cards', - filter_by: `sealed:false${languageFilter}${filterBy ? ` && ${filterBy}` : ''}`, + filter_by: `sealed:false${languageFilter}${queryFilter ? ` && ${queryFilter}` : ''}${filterBy ? ` && ${filterBy}` : ''}`, per_page: 20, facet_by: '', max_facet_values: 0, @@ -101,8 +117,8 @@ if (start === 0) { const searchRequests = { searches: searchArray }; const commonSearchParams = { - q: query, - query_by: 'content' + q: resolvedQuery, + query_by: 'content,setName,productLineName,rarityName,energyType,cardType' }; // use typesense to search for cards matching the query and return the productIds of the results @@ -182,24 +198,24 @@ const facets = searchResults.results.slice(1).map((result: any) => { ))} -

