[feat] independent facets
This commit is contained in:
@@ -5,6 +5,17 @@ import RarityIcon from '../../components/RarityIcon.astro';
|
|||||||
|
|
||||||
export const prerender = false;
|
export const prerender = false;
|
||||||
|
|
||||||
|
// all the facet fields we want to use for filtering
|
||||||
|
const facetFields = {
|
||||||
|
"productLineName": "Product Line",
|
||||||
|
"setName": "Set",
|
||||||
|
"variant": "Variant",
|
||||||
|
"rarityName": "Rarity",
|
||||||
|
"cardType": "Card Type",
|
||||||
|
"energyType": "Energy Type"
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// get the query from post request using form data
|
// get the query from post request using form data
|
||||||
const formData = await Astro.request.formData();
|
const formData = await Astro.request.formData();
|
||||||
const query = formData.get('q')?.toString() || '';
|
const query = formData.get('q')?.toString() || '';
|
||||||
@@ -27,19 +38,53 @@ const filterBy = Object.entries(filters).map(([field, values]) => {
|
|||||||
return `${field}:=[${values.join(',')}]`;
|
return `${field}:=[${values.join(',')}]`;
|
||||||
}).join(' && ');
|
}).join(' && ');
|
||||||
|
|
||||||
// use typesense to search for cards matching the query and return the productIds of the results
|
const facetFilter = (facet:string) => {
|
||||||
const searchResults = await client.collections('cards').documents().search({
|
const otherFilters = Object.entries(filters)
|
||||||
q: query,
|
.filter(([field]) => field !== facet)
|
||||||
|
.map(([field, values]) => `${field}:=[${values.join(',')}]`)
|
||||||
|
.join(' && ');
|
||||||
|
return `sealed:false${otherFilters ? ` && ${otherFilters}` : ''}`;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// primary search values (for cards)
|
||||||
|
let searchArray = [{
|
||||||
|
collection: 'cards',
|
||||||
filter_by: `sealed:false${filterBy ? ` && ${filterBy}` : ''}`,
|
filter_by: `sealed:false${filterBy ? ` && ${filterBy}` : ''}`,
|
||||||
query_by: 'productLineName,productName,setName,number,rarityName,Artist',
|
|
||||||
per_page: 20,
|
per_page: 20,
|
||||||
facet_by: 'productLineName,setName,variant,rarityName,cardType,energyType',
|
facet_by: Object.keys(facetFields).join(','),
|
||||||
page: Math.floor(start / 20) + 1,
|
page: Math.floor(start / 20) + 1,
|
||||||
sort_by: '_text_match:asc, releaseDate:desc, productName:asc',
|
sort_by: '_text_match:asc, releaseDate:desc, productName:asc',
|
||||||
});
|
}];
|
||||||
const cardIds = searchResults.hits?.map((hit: any) => hit.document.cardId) ?? [];
|
|
||||||
const totalHits = searchResults.found;
|
// on first load (start === 0) we want to get the facets for the filters
|
||||||
const facets = searchResults.facet_counts;
|
if (start === 0) {
|
||||||
|
for (const facet of Object.keys(facetFields)) {
|
||||||
|
searchArray.push({
|
||||||
|
collection: 'cards',
|
||||||
|
filter_by: facetFilter(facet),
|
||||||
|
per_page: 0,
|
||||||
|
facet_by: facet,
|
||||||
|
page: 1,
|
||||||
|
sort_by: ''
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const searchRequests = { searches: searchArray };
|
||||||
|
const commonSearchParams = {
|
||||||
|
q: query,
|
||||||
|
query_by: 'productLineName,productName,setName,number,rarityName,Artist',
|
||||||
|
};
|
||||||
|
|
||||||
|
// use typesense to search for cards matching the query and return the productIds of the results
|
||||||
|
const searchResults = await client.multiSearch.perform(searchRequests, commonSearchParams);
|
||||||
|
//console.log(searchResults);
|
||||||
|
const cardResults = searchResults.results[0] as any;
|
||||||
|
|
||||||
|
const cardIds = cardResults.hits?.map((hit: any) => hit.document.cardId) ?? [];
|
||||||
|
const totalHits = cardResults?.found;
|
||||||
|
//const facets = cardResults?.facet_counts;
|
||||||
|
|
||||||
// get pokemon data with prices and set info using searchResults and then query the database for each card to get the prices and set info
|
// get pokemon data with prices and set info using searchResults and then query the database for each card to get the prices and set info
|
||||||
const pokemon = await db.query.cards.findMany({
|
const pokemon = await db.query.cards.findMany({
|
||||||
@@ -72,14 +117,14 @@ const conditionShort = (condition:string) => {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const facetNames = (name:string) => {
|
const facetNames = (name:string) => {
|
||||||
return {
|
return facetFields[name] || name;
|
||||||
"productLineName": "Product Line",
|
}
|
||||||
"setName": "Set",
|
|
||||||
"variant": "Variant",
|
if (start === 0) {
|
||||||
"rarityName": "Rarity",
|
var facets = searchResults.results.slice(1).map((result: any) => {
|
||||||
"cardType": "Card Type",
|
return result.facet_counts[0];
|
||||||
"energyType": "Energy Type"
|
});
|
||||||
}[name] || name;
|
console.log(facets);
|
||||||
}
|
}
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -89,13 +134,13 @@ const facetNames = (name:string) => {
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div id="facetContainer" hx-swap-oob="true">
|
<div id="facetContainer" hx-swap-oob="true">
|
||||||
|
<button type="submit" form="searchform" class="btn btn-secondary">Apply Filters</button>
|
||||||
{facets.map((facet) => (
|
{facets.map((facet) => (
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<div class="h5">{facetNames(facet.field_name)}</div>
|
<div class="h5">{facetNames(facet.field_name)}</div>
|
||||||
{facet.counts.map((count) => (
|
{facet.counts.map((count) => (
|
||||||
<div>
|
<div>
|
||||||
<label class="form-check-label">
|
<label class="form-check-label">
|
||||||
<!--<input type="checkbox" name={facet.field_name} value={count.value} class="form-check-input" hx-get="/partials/cards" hx-target="#cardGrid" hx-include="#searchform" hx-trigger="change" hx-swap="outerHTML" hx-on--after-request="afterUpdate(event)" /> -->
|
|
||||||
<input type="checkbox" name={facet.field_name} value={count.value} checked={filterChecked(facet.field_name, count.value)} class="form-check-input" form="searchform" />
|
<input type="checkbox" name={facet.field_name} value={count.value} checked={filterChecked(facet.field_name, count.value)} class="form-check-input" form="searchform" />
|
||||||
{count.value} ({count.count})
|
{count.value} ({count.count})
|
||||||
</label>
|
</label>
|
||||||
@@ -103,6 +148,7 @@ const facetNames = (name:string) => {
|
|||||||
))}
|
))}
|
||||||
</div>
|
</div>
|
||||||
))}
|
))}
|
||||||
|
<button type="submit" form="searchform" class="btn btn-secondary">Apply Filters</button>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user