Skip to main content
arrow_back Back to Blog
Search

Filter Strategy with Sitecore Search

6 min read

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:

  1. Programmatic filters applied on component load
  2. User-selected facet filters (accordion-based UI)
  3. 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

ClassPurpose
FilterEqualExact match on an attribute
FilterOrOR combination of multiple filters
FilterNotNegation filter (attribute doesn’t exist)
FilterAndAND combination of multiple filters

Best Practices Implemented

  1. Server-side context - Context is determined from useSitecoreContext()
  2. Hydration safety - Uses IsClient() check before accessing router queries
  3. Filter composability - Filters are modular and combined with FilterAnd
  4. URL state sync - Search state persists in URL for shareability