Integrating Laravel Scout with Typesense for Lightning-Fast Search

Overview

provides a seamless driver-based solution for adding full-text search to
Eloquent
models. While drivers for
Algolia
and
Meilisearch
are well-known,
Typesense
has emerged as a powerful, open-source alternative. It offers keyword, semantic, and vector search capabilities with incredible speed. Integrating it allows you to maintain the convenience of
Laravel
while utilizing a high-performance search engine that you can self-host or run in the cloud.

Prerequisites

To follow this guide, you should be comfortable with

and the
Laravel
framework. You will need an existing application with a database and
Eloquent
models ready for indexing. You also need a running
Typesense
server instance (local or cloud) and
Composer
installed for package management.

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

. You need both Scout and the
Typesense
PHP client.

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.

specifically requires the 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

scans when you execute a search. If you forget to add a field here, results won't appear even if the data is indexed. Also, ensure your 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:
    Typesense
    is strict about its schema. If you change your fields in config/scout.php, use php artisan scout:flush before re-importing to prevent conflicts.
  • Observers: Scout uses model observers. Standard Eloquent updates will sync to
    Typesense
    automatically, but mass updates via DB::table() will not.
3 min read