Filter Strategy with Sitecore Search
Filter Strategy with Sitecore Search
This document explains how the filter strategy is architected from initial load through user interactions.
Overview
The widget uses the @sitecore-search/react SDK to manage search state, apply filters, and retrieve faceted results. The filtering strategy combines:
- Programmatic filters applied on component load
- User-selected facet filters (accordion-based UI)
- URL query parameter integration for keyword search
Sitecore Search SDK Integration
The core of the search functionality relies on two hooks from @sitecore-search/react:
import {
FilterAnd,
WidgetDataType,
useSearchResults,
useSearchResultsQuery,
widget,
type SearchResultsStoreState,
} from "@sitecore-search/react";
useSearchResults Hook
This hook manages the search state and provides query results:
const {
widgetRef,
actions: { onPageNumberChange, onKeyphraseChange },
state: { page: currentPage = 1 },
queryResult: {
isLoading,
isFetching,
data: {
total_item: totalItems = 0,
facet: facets = [],
content: resourceItems = [],
} = {},
},
} = useSearchResults({
state: {
sortType: defaultSortType || "relevance",
keyphrase: key || "",
itemsPerPage: defaultItemsPerPage || 12,
selectedFacets: [],
},
});
Key features:
- Manages pagination state (
page,onPageNumberChange) - Handles keyphrase changes from URL parameters
- Returns facets for the accordion filter UI
- Returns content items (search results)
- Provides loading/fetching states
useSearchResultsQuery Hook
This hook provides access to modify the underlying search request:
const query = useSearchResultsQuery();
This is used to programmatically apply filters to the search request.
Filter Strategy from Load
When the widget mounts, it applies filters using a useEffect:
useEffect(() => {
const filters = getFilters();
// Apply combined filters
if (filters.length > 0) {
const combinedFilter =
filters.length > 1 ? new FilterAnd(filters) : filters[0];
query.getRequest().setSearchFilter(combinedFilter);
}
}, [query]);
Filter Combination Strategy
graph TD
A[Widget Load] --> B[Get Filters]
B --> C[Combine with FilterAnd]
C --> D[setSearchFilter on query]
D --> E[Sitecore Search API Request]
E --> F[Filtered Results + Facets]
The filters are combined using FilterAnd:
const combinedFilter = filters.length > 1 ? new FilterAnd(filters) : filters[0];
query.getRequest().setSearchFilter(combinedFilter);
URL Query Parameter Integration
The widget synchronizes with URL query parameters for keyword search:
const key = isClient && router.isReady ? (router.query.q as string) || "" : "";
useEffect(() => {
if (isClient && router.isReady) {
const currentQuery = (router.query.q as string) || "";
onKeyphraseChange({ keyphrase: currentQuery });
}
}, [isClient, router.isReady, router.query.q, onKeyphraseChange]);
This enables:
- Direct URL sharing with search queries
- Browser back/forward navigation support
- Hydration-safe query parameter reading
Facet-Based Filtering (User Interactions)
The widget renders facets using AccordionFacets:
<AccordionFacets
facets={updatedFacets}
clearFiltersLabel={fields?.clearFiltersLabel?.value}
refineResultsLabel={fields?.refineResultsLabel?.value}
/>
Facet Label Customization
Facets are dynamically labeled from CMS fields:
const updatedFacets = facets.map((facet) => {
if (facet.name === "product_categories_facet") {
facet.label = fields?.productTaxonomyFacetLabel?.value || facet.label;
}
if (facet.name === "document_types_facet") {
facet.label = fields?.resourceTypeFacetLabel?.value || facet.label;
}
return facet;
});
Architecture Flow
sequenceDiagram
participant User
participant Widget
participant SitecoreSearch
Widget->>Widget: Apply initial filters
Widget->>SitecoreSearch: setSearchFilter(combinedFilter)
SitecoreSearch-->>Widget: Results + Facets
Widget-->>User: Render filtered results
User->>Widget: Select facet
Widget->>SitecoreSearch: onFacetChange()
SitecoreSearch-->>Widget: Updated results
Widget-->>User: Re-render
Key Sitecore Search Filter Classes
| Class | Purpose |
|---|---|
FilterEqual | Exact match on an attribute |
FilterOr | OR combination of multiple filters |
FilterNot | Negation filter (attribute doesn’t exist) |
FilterAnd | AND combination of multiple filters |
Best Practices Implemented
- Server-side context - Context is determined from
useSitecoreContext() - Hydration safety - Uses
IsClient()check before accessing router queries - Filter composability - Filters are modular and combined with
FilterAnd - URL state sync - Search state persists in URL for shareability