Integrating Laravel Scout with Typesense for Lightning-Fast Search
Overview
Prerequisites
To follow this guide, you should be comfortable with
Key Libraries & Tools
- Laravel Scout: The official package for full-text search in Laravel.
- Typesense: An open-source, lightning-fast search engine.
- Typesense PHP SDK: The low-level client required for Scout to communicate with the Typesense API.
Code Walkthrough
1. Installation
First, pull in the necessary packages via
composer require laravel/scout
composer require typesense/typesense-php
Publish the Scout configuration file to your config directory:
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
2. Model Configuration
Add the Searchable trait to your model. You must also implement the toSearchableArray method. id as a string and typically a timestamp for the created_at field.
use Laravel\Scout\Searchable;
class Recipe extends Model
{
use Searchable;
public function toSearchableArray(): array
{
return array_merge($this->toArray(), [
'id' => (string) $this->id,
'created_at' => (int) $this->created_at->timestamp,
]);
}
}
3. Schema Definition
In config/scout.php, define the collection schema for your model. You must specify every field name and its corresponding data type (e.g., string, array, int32).
'typesense' => [
'model_settings' => [
Recipe::class => [
'collection_schema' => [
'fields' => [
['name' => 'name', 'type' => 'string'],
['name' => 'ingredients', 'type' => 'string[]'],
['name' => 'created_at', 'type' => 'int32'],
],
],
'search_parameters' => [
'query_by' => 'name,ingredients',
],
],
],
],
Syntax Notes
Pay close attention to the query_by parameter in your configuration. This comma-separated string determines which fields toSearchableArray types match your collection_schema types exactly to avoid indexing errors.
Practical Examples
Once configured, searching is as simple as calling the search method on your model. You can perform complex queries like searching for "Pasta" within specific ingredients or cuisines.
// Simple keyword search
$results = Recipe::search('Pizza')->get();
// Searching multiple fields defined in query_by
$results = Recipe::search('Sugar')->get();
Tips & Gotchas
- Initial Import: Your existing database records won't sync automatically. Run
php artisan scout:import "App\Models\Recipe"to populate your index. - Schema Updates: Typesenseis strict about its schema. If you change your fields in
config/scout.php, usephp artisan scout:flushbefore re-importing to prevent conflicts. - Observers: Scout uses model observers. Standard Eloquent updates will sync to Typesenseautomatically, but mass updates via
DB::table()will not.
