PHPackages                             hocvt/laravel-scout-elasticsearch - PHPackages - PHPackages  [Skip to content](#main-content)[PHPackages](/)[Directory](/)[Categories](/categories)[Trending](/trending)[Leaderboard](/leaderboard)[Changelog](/changelog)[Analyze](/analyze)[Collections](/collections)[Log in](/login)[Sign up](/register)

1. [Directory](/)
2. /
3. [Search &amp; Filtering](/categories/search)
4. /
5. hocvt/laravel-scout-elasticsearch

ActiveLibrary[Search &amp; Filtering](/categories/search)

hocvt/laravel-scout-elasticsearch
=================================

Search among multiple models with ElasticSearch and Laravel Scout

v7.11.0(10mo ago)0848↓50%MITPHP ^8.0.12|^8.1

Since May 2Pushed 10mo agoCompare

[ Source](https://github.com/vuthaihoc/laravel-scout-elasticsearch)[ Packagist](https://packagist.org/packages/hocvt/laravel-scout-elasticsearch)[ Patreon](https://www.patreon.com/matchish)[ RSS](/packages/hocvt-laravel-scout-elasticsearch/feed)WikiDiscussions dev Synced 1mo ago

READMEChangelog (1)Dependencies (9)Versions (3)Used By (0)

Stay with Ukraine
=================

[](#stay-with-ukraine)

[UNITED24](https://u24.gov.ua/robots_fight) launches the first fundraiser towards terrestrial robotic platforms. Squads of robots will save the lives of our military and civilians. They will become logistics devices, tow trucks, minelayers and deminers, as well as self-destructive robots. They will fight alongside people and for people.

The first robots are already proving their effectiveness on the battlefield. There will be more of them soon. Many more.

[![Support Ukraine](https://camo.githubusercontent.com/cb80dffa931836cf4173f829d3d67f6cce0a40b00ac6725b3cedca018b6e2f1f/68747470733a2f2f66696c65732e7532342e676f762e75612f70616765732f726f626f747346696768742f5f70726f6365737365642f726f626f74732d6f672d656e2e6a7067)](https://u24.gov.ua/robots_fight)[![Import progress report](https://raw.githubusercontent.com/matchish/laravel-scout-elasticsearch/master/docs/demo.gif)](https://raw.githubusercontent.com/matchish/laravel-scout-elasticsearch/master/docs/demo.gif)

 [![Build Status](https://github.com/matchish/laravel-scout-elasticsearch/actions/workflows/test-application.yaml/badge.svg)](#) [![Coverage](https://camo.githubusercontent.com/5b1055b16eb504f59c9789d46ee658541a6edccea734832cff4bdfa37eb87db0/68747470733a2f2f636f6465636f762e696f2f67682f6d617463686973682f6c61726176656c2d73636f75742d656c61737469637365617263682f6272616e63682f636f7665726167652d62616467652f67726170682f62616467652e737667)](https://app.codecov.io/gh/matchish/laravel-scout-elasticsearch) [![Total Downloads](https://camo.githubusercontent.com/c7f319c85e0ed45a9a3a753527dc0722a00503db4a69138bc607b5e7f84aeadd/68747470733a2f2f706f7365722e707567782e6f72672f6d617463686973682f6c61726176656c2d73636f75742d656c61737469637365617263682f642f746f74616c2e737667)](https://packagist.org/packages/matchish/laravel-scout-elasticsearch) [![Latest Version](https://camo.githubusercontent.com/4d515f3d6bb97c9f71903009b25f408446c8935b697f51112f661ec6f4e6d134/68747470733a2f2f706f7365722e707567782e6f72672f6d617463686973682f6c61726176656c2d73636f75742d656c61737469637365617263682f762f737461626c652e737667)](https://packagist.org/packages/matchish/laravel-scout-elasticsearch) [![License](https://camo.githubusercontent.com/dfef7487193b120dfb01a97ace414c6584ac78c97f46d41e241476f3436c8d35/68747470733a2f2f706f7365722e707567782e6f72672f6d617463686973682f6c61726176656c2d73636f75742d656c61737469637365617263682f6c6963656e73652e737667)](https://packagist.org/packages/matchish/laravel-scout-elasticsearch)

#### For Laravel Framework &lt; 6.0.0 use [3.x](https://github.com/matchish/laravel-scout-elasticsearch/tree/3.x) branch

[](#for-laravel-framework--600-use-3x-branch)

The package provides the perfect starting point to integrate ElasticSearch into your Laravel application. It is carefully crafted to simplify the usage of ElasticSearch within the [Laravel Framework](https://laravel.com).

It’s built on top of the latest release of [Laravel Scout](https://laravel.com/docs/scout), the official Laravel search package. Using this package, you are free to take advantage of all of Laravel Scout’s great features, and at the same time leverage the complete set of ElasticSearch’s search experience.

💕 Features
----------

[](#two_hearts-features)

Don't forget to ⭐ the package if you like it. 🙏

- Laravel Scout 10.x support
- Laravel Nova support
- [Search amongst multiple models](#search-amongst-multiple-models)
- [**Zero downtime** reimport](#zero-downtime-reimport) - it’s a breeze to import data in production.
- [Eager load relations](#eager-load) - speed up your import.
- Parallel import to make your import as fast as possible (in [alpha version](https://github.com/matchish/laravel-scout-elasticsearch/releases/tag/8.0.0-alpha.1) for now)
- Import all searchable models at once.
- A fully configurable mapping for each model.
- Full power of ElasticSearch in your queries.

⚠️ Requirements
---------------

[](#warning-requirements)

- PHP version &gt;= 8.0
- Laravel Framework version &gt;= 8.0.0

Elasticsearch versionElasticsearchDSL version&gt;= 8.0&gt;= 8.0.0&gt;= 7.0&gt;= 3.0.0&gt;= 6.0, &lt; 7.0&lt; 3.0.0🚀 Installation
--------------

[](#rocket-installation)

Use composer to install the package:

```
composer require matchish/laravel-scout-elasticsearch

```

Set env variables

```
SCOUT_DRIVER=Matchish\ScoutElasticSearch\Engines\ElasticSearchEngine

```

The package uses `\ElasticSearch\Client` from official package, but does not try to configure it beyond connection configuration, so feel free do it in your app service provider. But if you don't want to do it right now, you can use `Matchish\ElasticSearchServiceProvider` from the package.
Register the provider, adding to `config/app.php`

```
'providers' => [
    // Other Service Providers

    \Matchish\ScoutElasticSearch\ElasticSearchServiceProvider::class
],
```

Set `ELASTICSEARCH_HOST` env variable

```
ELASTICSEARCH_HOST=host:port

```

or use commas as separator for additional nodes

```
ELASTICSEARCH_HOST=host:port,host:port

```

You can disable SSL verification by setting the following in your env

```
ELASTICSEARCH_SSL_VERIFICATION=false

```

And publish config example for elasticsearch
`php artisan vendor:publish --tag config`

💡 Usage
-------

[](#bulb-usage)

> **Note:** This package adds functionalities to [Laravel Scout](https://github.com/laravel/scout), and for this reason, we encourage you to **read the Scout documentation first**. Documentation for Scout can be found on the [Laravel website](https://laravel.com/docs/scout).

### Index [settings](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html#create-index-settings) and [mappings](https://www.elastic.co/guide/en/elasticsearch/reference/current/indices-create-index.html#mappings)

[](#index-settings-and-mappings)

It is very important to define the mapping when we create an index — an inappropriate preliminary definition and mapping may result in the wrong search results.

To define mappings or settings for index, set config with right value.

For example if method `searchableAs` returns `products` string

Config key for mappings should be
`elasticsearch.indices.mappings.products`
Or you you can specify default mappings with config key `elasticsearch.indices.mappings.default`

Same way you can define settings

For index `products` it will be
`elasticsearch.indices.settings.products`

And for default settings
`elasticsearch.indices.settings.default`

### Eager load

[](#eager-load)

To speed up import you can eager load relations on import using global scopes.

You should configure `ImportSourceFactory` in your service provider(`register` method)

```
use Matchish\ScoutElasticSearch\Searchable\ImportSourceFactory;
...
public function register(): void
{
$this->app->bind(ImportSourceFactory::class, MyImportSourceFactory::class);
```

Here is an example of `MyImportSourceFactory`

```
namespace Matchish\ScoutElasticSearch\Searchable;

final class MyImportSourceFactory implements ImportSourceFactory
{
    public static function from(string $className): ImportSource
    {
        //Add all required scopes
        return new DefaultImportSource($className, [new WithCommentsScope()]);
    }
}

class WithCommentsScope implements Scope {

    /**
     * Apply the scope to a given Eloquent query builder.
     *
     * @param \Illuminate\Database\Eloquent\Builder $builder
     * @param \Illuminate\Database\Eloquent\Model $model
     * @return void
     */
    public function apply(Builder $builder, Model $model)
    {
        $builder->with('comments');
    }
}
```

You can also customize your indexed data when you save models by leveraging the [`toSearchableArray`](https://laravel.com/docs/9.x/scout#configuring-searchable-data) method provided by Laravel Scout through the `Searchable` trait

#### Example:

[](#example)

```
class Product extends Model
{
    use Searchable;

    /**
     * Get the indexable data array for the model.
     *
     * @return array
     */
    public function toSearchableArray()
    {
        $with = [
            'categories',
        ];

        $this->loadMissing($with);

        return $this->toArray();
    }
}
```

This example will make sure the categories relationship gets always loaded on the model when saving it.

### Zero downtime reimport

[](#zero-downtime-reimport)

While working in production, to keep your existing search experience available while reimporting your data, you also can use `scout:import` Artisan command:

`php artisan scout:import`

The command create new temporary index, import all models to it, and then switch to the index and remove old index.

### Search

[](#search)

To be fully compatible with original scout package, this package does not add new methods.
So how we can build complex queries? There is two ways.
By default, when you pass a query to the `search` method, the engine builds a [query\_string](https://www.elastic.co/guide/en/elasticsearch/reference/current/query-dsl-query-string-query.html) query, so you can build queries like this

```
Product::search('(title:this OR description:this) AND (title:that OR description:that)')
```

If it's not enough in your case you can pass a callback to the query builder

```
$results = Product::search('zonga', function(\Elastic\Elasticsearch\Client $client, $body) {

    $minPriceAggregation = new MinAggregation('min_price');
    $minPriceAggregation->setField('price');

    $maxPriceAggregation = new MaxAggregation('max_price');
    $maxPriceAggregation->setField('price');

    $brandTermAggregation = new TermsAggregation('brand');
    $brandTermAggregation->setField('brand');

    $body->addAggregation($minPriceAggregation);
    $body->addAggregation($brandTermAggregation);

    return $client->search(['index' => 'products', 'body' => $body->toArray()])->asArray();
})->raw();
```

> Note : The callback function will get 2 parameters. First one is `$client` and it is an object of `\Elastic\Elasticsearch\Client`class from [elasticsearch/elasticsearch](https://packagist.org/packages/elasticsearch/elasticsearch) package. And the second one is `$body` which is an object of `\ONGR\ElasticsearchDSL\Search` from [ongr/elasticsearch-dsl](https://packagist.org/packages/handcraftedinthealps/elasticsearch-dsl) package. So, while as you can see the example above, `$client->search(....)` method will return an `\Elastic\Elasticsearch\Response\Elasticsearch` object. And you need to use `asArray()` method to get array result. Otherwise, the `HitsIteratorAggregate` class will throw an error. You can check the issue [here](https://github.com/matchish/laravel-scout-elasticsearch/issues/215).

### Conditions

[](#conditions)

Scout supports only 3 conditions: `->where(column, value)` (strict equation), `->whereIn(column, array)` and `->whereNotIn(column, array)`:

```
Product::search('(title:this OR description:this) AND (title:that OR description:that)')
    ->where('price', 100)
    ->whereIn('type', ['used', 'like new'])
    ->whereNotIn('type', ['new', 'refurbished']);
```

Scout does not support any operators, but you can pass ElasticSearch terms like `RangeQuery` as value to `->where()`:

```
use ONGR\ElasticsearchDSL\Query\TermLevel\RangeQuery;

Product::search('(title:this OR description:this) AND (title:that OR description:that)')
    ->where('price', new RangeQuery('price', [
        RangeQuery::GTE => 100,
        RangeQuery::LTE => 1000,
    ]);
```

And if you just want to search using RangeQuery without any query\_string, you can call the search() method directly and leave the param empty.

```
use ONGR\ElasticsearchDSL\Query\TermLevel\RangeQuery;

Product::search()
    ->where('price', new RangeQuery('price', [
        RangeQuery::GTE => 100,
    ]);
```

Full list of ElasticSearch terms is in `vendor/handcraftedinthealps/elasticsearch-dsl/src/Query/TermLevel`.

### Limiting returned fields

[](#limiting-returned-fields)

Sometimes your indexed models have fields that should not appear in returned result. You can set returned fields in `source` option `->options(['source' => ['this', 'that', 'something', 'else']])`

### Pagination

[](#pagination)

The engine supports [Elasticsearch pagination](https://www.elastic.co/guide/en/elasticsearch/reference/current/paginate-search-results.html)with [Scout Builder pagination](https://laravel.com/docs/11.x/scout#pagination) or by setting page sizes and offsets using the `->take($size)` method and `->options(['from' => $from])`.

> Caution : Builder pagination takes precedence over the `take()` and `options()` setting.

For example:

```
Product::search()
    ->take(20)
    ->options([
        'from' => 20,
    ])
    ->paginate(50);
```

This will return the first 50 results, ignoring the specified offset.

### Search amongst multiple models

[](#search-amongst-multiple-models)

You can do it with `MixedSearch` class, just pass indices names separated by commas to the `within` method.

```
MixedSearch::search('title:Barcelona or to:Barcelona')
    ->within(implode(',', [
        (new Ticket())->searchableAs(),
        (new Book())->searchableAs(),
    ]))
    ->get();
```

In this example you will get collection of `Ticket` and `Book` models where ticket's arrival city or book title is `Barcelona`

### Working with results

[](#working-with-results)

Often your response isn't collection of models but aggregations or models with higlights and so on. In this case you need to implement your own implementation of `HitsIteratorAggregate` and bind it in your service provider

[Here is a case](https://github.com/matchish/laravel-scout-elasticsearch/issues/28)

🆓 License
---------

[](#free-license)

Scout ElasticSearch is an open-sourced software licensed under the [MIT license](LICENSE.md).

###  Health Score

36

—

LowBetter than 82% of packages

Maintenance54

Moderate activity, may be stable

Popularity17

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity47

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 74.8% of commits — single point of failure

How is this calculated?**Maintenance (25%)** — Last commit recency, latest release date, and issue-to-star ratio. Uses a 2-year decay window.

**Popularity (30%)** — Total and monthly downloads, GitHub stars, and forks. Logarithmic scaling prevents top-heavy scores.

**Community (15%)** — Contributors, dependents, forks, watchers, and maintainers. Measures real ecosystem engagement.

**Maturity (30%)** — Project age, version count, PHP version support, and release stability.

###  Release Activity

Cadence

Unknown

Total

1

Last Release

321d ago

### Community

Maintainers

![](https://avatars.githubusercontent.com/u/2509658?v=4)[Stupid Dev](/maintainers/vuthaihoc)[@vuthaihoc](https://github.com/vuthaihoc)

---

Top Contributors

[![matchish](https://avatars.githubusercontent.com/u/818563?v=4)](https://github.com/matchish "matchish (488 commits)")[![hkulekci](https://avatars.githubusercontent.com/u/586318?v=4)](https://github.com/hkulekci "hkulekci (53 commits)")[![ametad](https://avatars.githubusercontent.com/u/1582541?v=4)](https://github.com/ametad "ametad (28 commits)")[![burakcakirel](https://avatars.githubusercontent.com/u/3121372?v=4)](https://github.com/burakcakirel "burakcakirel (15 commits)")[![Orest-Divintari](https://avatars.githubusercontent.com/u/9808549?v=4)](https://github.com/Orest-Divintari "Orest-Divintari (11 commits)")[![jalmatari](https://avatars.githubusercontent.com/u/2941118?v=4)](https://github.com/jalmatari "jalmatari (7 commits)")[![Fayne](https://avatars.githubusercontent.com/u/3952854?v=4)](https://github.com/Fayne "Fayne (7 commits)")[![yocmen](https://avatars.githubusercontent.com/u/11200640?v=4)](https://github.com/yocmen "yocmen (6 commits)")[![SineMah](https://avatars.githubusercontent.com/u/8180962?v=4)](https://github.com/SineMah "SineMah (5 commits)")[![royduin](https://avatars.githubusercontent.com/u/1703233?v=4)](https://github.com/royduin "royduin (4 commits)")[![hulkur](https://avatars.githubusercontent.com/u/11457732?v=4)](https://github.com/hulkur "hulkur (3 commits)")[![ganicus](https://avatars.githubusercontent.com/u/1510161?v=4)](https://github.com/ganicus "ganicus (2 commits)")[![jackraymund](https://avatars.githubusercontent.com/u/8265560?v=4)](https://github.com/jackraymund "jackraymund (2 commits)")[![Jade-GG](https://avatars.githubusercontent.com/u/32514269?v=4)](https://github.com/Jade-GG "Jade-GG (2 commits)")[![StyleCIBot](https://avatars.githubusercontent.com/u/11048387?v=4)](https://github.com/StyleCIBot "StyleCIBot (2 commits)")[![vuthaihoc](https://avatars.githubusercontent.com/u/2509658?v=4)](https://github.com/vuthaihoc "vuthaihoc (2 commits)")[![rafaucau](https://avatars.githubusercontent.com/u/25438601?v=4)](https://github.com/rafaucau "rafaucau (2 commits)")[![vrusua](https://avatars.githubusercontent.com/u/2073317?v=4)](https://github.com/vrusua "vrusua (1 commits)")[![youanden](https://avatars.githubusercontent.com/u/183880?v=4)](https://github.com/youanden "youanden (1 commits)")[![mackhankins](https://avatars.githubusercontent.com/u/2184080?v=4)](https://github.com/mackhankins "mackhankins (1 commits)")

---

Tags

searchlaravelelasticsearchextendedscout

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/hocvt-laravel-scout-elasticsearch/health.svg)

```
[![Health](https://phpackages.com/badges/hocvt-laravel-scout-elasticsearch/health.svg)](https://phpackages.com/packages/hocvt-laravel-scout-elasticsearch)
```

###  Alternatives

[matchish/laravel-scout-elasticsearch

Search among multiple models with ElasticSearch and Laravel Scout

7431.6M2](/packages/matchish-laravel-scout-elasticsearch)[jeroen-g/explorer

Next-gen Elasticsearch driver for Laravel Scout.

397612.3k](/packages/jeroen-g-explorer)

PHPackages © 2026

[Directory](/)[Categories](/categories)[Trending](/trending)[Changelog](/changelog)[Analyze](/analyze)
