Database & Search8 min read

How to Use Elasticsearch with Laravel for Advanced Search

Md Shahed Alam
Md Shahed Alam
February 18, 2025
How to Use Elasticsearch with Laravel for Advanced Search

MySQL full-text search is good enough for small apps. But once you have tens of thousands of products and users who type with typos, it starts to fall short. Elasticsearch was built specifically for search, and the difference in quality is significant.

Here is how I integrated it into a Laravel e-commerce project.

What Elasticsearch actually does differently

When you search for "wireles headphons" in MySQL full-text search, you get zero results. Elasticsearch understands that you probably meant "wireless headphones" and returns the right products anyway. This is called fuzzy matching.

Elasticsearch also ranks results by relevance. A product named "Wireless Headphones" ranks higher than one that just mentions headphones in the description. MySQL does not do this well.

Setting up the PHP client

bash
composer require elasticsearch/elasticsearch

Create a service class:

php
class SearchService {
    private Client $client;
    
    public function __construct() {
        $this->client = ClientBuilder::create()
            ->setHosts([config('services.elasticsearch.host')])
            ->build();
    }
    
    public function indexProduct(Product $product): void {
        $this->client->index([
            'index' => 'products',
            'id' => $product->id,
            'body' => [
                'name' => $product->name,
                'description' => $product->description,
                'price' => $product->price,
                'category' => $product->category->name,
                'in_stock' => $product->stock > 0,
            ],
        ]);
    }
}

Keeping the index in sync

Use a model observer to update Elasticsearch whenever a product changes:

php
class ProductObserver {
    public function __construct(private SearchService $search) {}
    
    public function saved(Product $product): void {
        $this->search->indexProduct($product);
    }
    
    public function deleted(Product $product): void {
        $this->search->deleteProduct($product->id);
    }
}

Searching with fuzzy matching

php
public function search(string $query, int $page = 1): array {
    $results = $this->client->search([
        'index' => 'products',
        'body' => [
            'query' => [
                'multi_match' => [
                    'query' => $query,
                    'fields' => ['name^3', 'description', 'category'],
                    'fuzziness' => 'AUTO',
                ],
            ],
            'filter' => [
                'term' => ['in_stock' => true]
            ],
            'from' => ($page - 1) * 20,
            'size' => 20,
        ],
    ]);
    
    $ids = collect($results['hits']['hits'])->pluck('_id');
    return Product::whereIn('id', $ids)->get();
}

The ^3 after name means matches in the product name are 3 times more relevant than matches in the description. fuzziness: AUTO handles typos automatically.

Using Laravel Scout

If you want a simpler integration, Laravel Scout with the babenkoivan/elastic-scout-driver package gives you Elasticsearch search with much less code. It is a good starting point.

When is Elasticsearch worth the complexity?

Elasticsearch adds infrastructure complexity. You need to run and maintain an Elasticsearch cluster. For a small app with 10,000 products, MySQL full-text search is probably fine.

Add Elasticsearch when: your dataset is large (100k+ records), typo tolerance is important, you need faceted search (filter by price range, category, rating), or search is a core feature of your product.

ElasticsearchLaravelSearchBackend

Ready to build something great?

Let's talk about your project. We will give you honest advice, a clear plan, and a fair price. No pressure, no sales pitch.

Free consultation
No commitment required
Response within 24 hours