Close-up view of binoculars on a surface with sunset reflection in lenses.

Laravel Scout with Typesense Facet Filters

Laravel Scout provides a convenient way to integrate search functionality into your application, but when using Typesense, you might notice that facets aren’t included in the default search method.

This article demonstrates how to properly add facet filters to your Typesense searches in Laravel Scout.

Basic Implementation

Here’s a simplified implementation that shows how to add facets to your Laravel Scout search with Typesense by using the raw method:

public function index()
{
    // Start with a basic search query
    $query = Product::search('my searchterm');
    
    // Prepare filter conditions
    $filterBy = [];
    
    // For example, price larger than 100 or your own custom set filter
    $filterBy[] = 'price:>=100';
    
    // Apply Typesense-specific options if you'd like
    $query->options([
        'query_by' => 'name',
        'filter_by' => implode(' && ', $filterBy),
        'facet_by' => 'brand,category,price', // Request these facets from Typesense, make sure that those facets are available
        'sort_by' => $request->input('sort_by', 'relevance:desc')
    ]);
    
    // Get paginated results
    $results = $query->paginate(24);
    
    // Add facet counts to the paginated results
    $results->facetCounts = $this->getFacets($query);
    
    return $results;
}

/**
 * Get facets from the Typesense search results
 */
private function getFacets($query)
{
    $raw = $query->raw();
    return $raw['facet_counts'] ?? [];
}

Optional: Reformatting Facets for Easier Use

You can also reformat the facets to make them easier to work with in your application:

/**
 * Reformat Typesense facets for easier use
 * 
 * @param array $facets The raw facet counts from Typesense
 * @return \Illuminate\Support\Collection
 */
private function reformatFacets(array $facets): \Illuminate\Support\Collection
{
    $result = collect();
    
    foreach ($facets as $facet) {
        $fieldName = $facet['field_name'] ?? null;
        
        if (!$fieldName) {
            continue;
        }
        
        $counts = collect($facet['counts'] ?? [])->map(function($item) {
            return [
                'value' => $item['value'],
                'count' => $item['count']
            ];
        });
        
        $result[$fieldName] = $counts;
    }
    
    return $result;
}

Using the Facets in Your Application

To use the reformatted facets, simply modify the previous search method:

// Get paginated results
$results = $query->paginate(24);

// Get raw facet counts from Typesense
$facets = $query->raw()['facet_counts'] ?? [];

// Add reformatted facets to the paginated results
$results->facetCounts = $this->reformatFacets($facets);

return $results;

Key Points to Remember

  • Use the facet_by option to specify which fields you want facets for
  • Access the raw facet data from the search query with $query->raw()['facet_counts']
  • Consider reformatting the facets to make them easier to work with in your application
  • Attach the facets to your paginated results so they’re accessible in your views

By implementing these techniques, you can easily add powerful faceted filtering capabilities to your Laravel application with Typesense, allowing users to refine their search results by various criteria.

Leave a Comment

Your email address will not be published. Required fields are marked *

en_USEnglish
Scroll to Top