PHPackages                             nailfor/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. [Database &amp; ORM](/categories/database)
4. /
5. nailfor/elasticsearch

ActiveLibrary[Database &amp; ORM](/categories/database)

nailfor/elasticsearch
=====================

Eloquent like library for Elasticsearch

v0.19.1(1y ago)03.4k1MITPHPPHP &gt;=7.1.0

Since Sep 21Pushed 1y ago2 watchersCompare

[ Source](https://github.com/nailfor/Elasticsearch)[ Packagist](https://packagist.org/packages/nailfor/elasticsearch)[ RSS](/packages/nailfor-elasticsearch/feed)WikiDiscussions master Synced today

READMEChangelogDependencies (1)Versions (50)Used By (0)

PHP Elasticsearch client for Laravel
====================================

[](#php-elasticsearch-client-for-laravel)

Elasticsearch client for Eloquent ORM

Installation
------------

[](#installation)

The preferred way to install this extension is through [composer](http://getcomposer.org/download/).

Either run

```
composer require nailfor/elasticsearch

```

or add

```
"nailfor/elasticsearch" : "*"
```

to the require section of your application's `composer.json` file.

Usage
-----

[](#usage)

Add config/app.php

```
    'providers' => [
        ...
        nailfor\Elasticsearch\ElasticsearchServiceProvider::class,

```

and config/database.php

```
    'connections' => [
        ...
        'elasticsearch' => [ //the name of connection in your models(default)
            'driver'    => 'elasticearch',
            'config'    => [
                'BasicAuthentication' => [
                    env('ELASTICSEARCH_LOGIN', ''),
                    env('ELASTICSEARCH_PASSWORD', ''),
                ],
                'hosts'     => [
                    env('ELASTICSEARCH_HOST', 'localhost:9200'),
                ],
                'retries'   => 1,
            ],
        ],

```

Example model
=============

[](#example-model)

```
namespace App\Models\db\elastic;

use nailfor\Elasticsearch\Eloquent\Model;

class esSearch extends Model
{
    //protected $connection = 'elasticsearch'; //(default)

    //your index name
    protected $table='index';
}

```

Example select
==============

[](#example-select)

```
esSearch::where('field', 'somedata')
    ->whereBetween('@timestamp', [$startDate, $endDate])
    ->whereIn('data.field', [1,3,4])
    ->whereFiledExist('some.field')
    ->whereFiledNotExist('another.field')
    ->get();

```

!!!ATTENTION!!! After v0.17.0 groups returns the query result!

Example groups
==============

[](#example-groups)

```
esSearch::where('field.data', 'somedata')
    //group name "group" by field "data.field" without subgroups
    ->groupBy(['group'=>'data.field'])

    //group name "some_field" by field "some_field"
    ->groupBy('some_field')
    //subgroup name "another" by field "another" and subgroup name "diff" and field "diff.name"
    ->groupBy('some_field', ['another', 'diff'=>'field.diff'])

    //another style
    ->groupBy(['grp'=>'field'], ['subgrp'=>'sub.field'])

esSearch::where('field.data', 'somedata')
    //group name "group" by field "data.field" without subgroups with limit 10 items
    ->groupBy(['group' => 'data.field'])
    ->limit(10)

//supported closure
esSearch::groupBy(['aggregation_name' => 'field.data'], fn ($query) => $query
    ->groupBy('some_field', fn ($subQuery) => $subQuery
        ->groupBy(['agg3' => 'another.field'])
    )
)

```

Range aggregations
==================

[](#range-aggregations)

```
    //group field "price" by 3 group: 2000
    ->groupByRange('price', ['ranges'=>[['to' => '1000'], ['from' => '1000', 'to' => 2000], ['from'=>2000]]])

```

Date aggregations
=================

[](#date-aggregations)

```
    //group "group" by 2 dates: before NOW-1Day and after. This is NOT filter, this is group by condition!
    //all groups with name "group" will be merged
    ->groupByDateRange(['group'=>'date.field'], ['ranges'=>['to' => 'now-1y/d', 'from' => 'now-1y/d']])

```

Interval aggregations
=====================

[](#interval-aggregations)

```
    //group "date.field" by interval "hour"
    ->groupByInterval(['graph'=>'date.field'], ['interval' => 'hour'])

```

Average aggregations
====================

[](#average-aggregations)

```
    //group and calculate average value
    ->groupBy(['groupName' => 'field_for_group'])
    ->groupByAverage('groupName', ['field' => 'field.name'])

```

Min/max aggregations
====================

[](#minmax-aggregations)

```
    ->groupByMin('groupName', ['field' => 'field.name'])
    ->groupByMax('groupName', ['field' => 'field.name'])

```

Sum aggregations
================

[](#sum-aggregations)

```
    //group and calculate sum
    ->groupBy(['groupName' => 'field_for_group'])
    ->groupBySum('groupName', ['field' => 'field.name'])

```

Nested aggregations
===================

[](#nested-aggregations)

```
//simple group 'nested_field' same of 'nested_field'
esSearch::groupByNested('nested_field')

    //group name 'nested_group' by field 'nested.field'
    ->groupByNested(['nested_group' => 'nested.field'])

    //By closures
    ->groupByNested(['nested_group' => 'nested.field'], fn ($query) => $query
        ->groupBy('some_field', fn ($subQuery) => $subQuery
            ->groupBy(['agg3' => 'another.field'])
        )
    )

```

Stats aggregations
==================

[](#stats-aggregations)

```
esSearch::groupByStats('some_field')
    // or
    ->groupByStats(['group_name' => 'some_field'])

//You can combine them together
esSearch::groupByNested('nested_field', fn($query) =>
    $query->groupBy(['group' => 'field.id'], fn($query) => $query
        ->groupByStats(['values' => 'properties.value'])
    )
)

```

Example fuzziness
=================

[](#example-fuzziness)

```
$query = esSearch::query($searchString, [
    'fuzziness' => 1,
]);
$collection = $query->get();

```

Example scroll API
==================

[](#example-scroll-api)

```
$query = esSearch::scroll([
        'scroll' => '1m',
    ]);
$collection = $query->get(); //first 10k(max) records
$collection = $query->get(); //next 10k(max) records...

```

or

```
esSearch::scroll([
        'scroll' => '1m',
    ])
    ->chunk(1000, function ($collection) {
        ...
    });

```

Example suggest request
=======================

[](#example-suggest-request)

```
//clear
esSeartch::where('model', 'short')
    ->suggest('my-suggest')
    ->get();

//closure
esSeartch::suggest('my-clossure', fn ($query) => $query->where('color', 'black'))
    ->get();

//mix
$query = esSeartch::select([
        'brand',
        'name',
    ])
    ->query($searchString, [
        'minimum_should_match'=> '50%',
        'fuzziness' => 'auto',
    ])
    ->suggest('my-1', fn ($query) => $query->where('size', 'xxl'))
    ->suggest('my-2', fn ($query) => $query->where('color', 'black'))
    ->suggest('my-3') //do nothing because there no "where" section
    ;
$collection = $query->get();

```

Example nested request
======================

[](#example-nested-request)

```
$query = esSeartch::select([])
    ->where('category.id', 2)   //Attention!
    ->nested('category')        //Condition category.id = 2 will be removed from the main body
    ->where('price', 100)       //But this condition will be added to the main body

    //also u can combine simple and complicated nested requests
    ->nested('brand', fn ($subQuery) => $subQuery           //$subQuery doesn't consist any conditions from the body
        ->whereIn('brand.id', ['Nike', 'Sony', 'LG'])
        ->nested('color', fn($subSubQuery) => $subSubQuery  //Also $subSubQuery doesn't consist conditions
            ->whereIn('color.group', ['red', 'green'])      //Both of them doesn't affected the body condition 'price = 100'
        )
    )
    ->orNested('property', fn(subQuery) => $subQuery
        ->where('property.value', 'milked')
    )

```

Example bulk insert
===================

[](#example-bulk-insert)

```
$records = [
    [
        '_id' => 1,  //This is field MUST be into recordset, otherwise will be set uniqid()
        'field1' => 'data1',
        'field2' => 'data2',
    ],
    [
        '_id' => 2,
        'field1' => 'some data1',
        'field2' => 'some data2',
    ],

];
esSeartch::insert($records);

```

Example post\_filter
====================

[](#example-post_filter)

```
$query = esSearch::groupBy(['group' => 'field.id'])
    ->postFilter(fn($query) => $query
        ->where('field', 'value')
        ->nested('category')
    )

```

Debug
=====

[](#debug)

$query = esSearch::query() -&gt;dd(true) //default false ;

Credits
-------

[](#credits)

- [nailfor](https://github.com/nailfor)

License
-------

[](#license)

The GNU License (GNU). Please see [License File](LICENSE.md) for more information.

###  Health Score

33

—

LowBetter than 72% of packages

Maintenance39

Infrequent updates — may be unmaintained

Popularity20

Limited adoption so far

Community11

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 77.3% 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

Every ~33 days

Recently: every ~48 days

Total

48

Last Release

527d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/1f0e23d07efd81dccb69223c1ef1897b2aa0d3eb74d7b2ee3627160406d43334?d=identicon)[nailfor](/maintainers/nailfor)

---

Top Contributors

[![365g1s22](https://avatars.githubusercontent.com/u/4192418?v=4)](https://github.com/365g1s22 "365g1s22 (34 commits)")[![nailfor](https://avatars.githubusercontent.com/u/13346879?v=4)](https://github.com/nailfor "nailfor (10 commits)")

---

Tags

elasticsearcheloquent

### Embed Badge

![Health badge](/badges/nailfor-elasticsearch/health.svg)

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

###  Alternatives

[elasticquent/elasticquent

Maps Laravel Eloquent models to Elasticsearch types.

1.4k957.8k2](/packages/elasticquent-elasticquent)[sleimanx2/plastic

Plastic is an Elasticsearch ODM and mapper for Laravel. It renders the developer experience more enjoyable while using Elasticsearch by providing a fluent syntax for mapping , querying and storing eloquent models.

508142.2k1](/packages/sleimanx2-plastic)[iverberk/larasearch

Elasticsearch enabled Eloquent models

22315.5k](/packages/iverberk-larasearch)[designmynight/laravel-elasticsearch

Use Elasticsearch as a database in Laravel to retrieve Eloquent models and perform aggregations.

3142.2k](/packages/designmynight-laravel-elasticsearch)[isswp101/elasticsearch-eloquent

Elasticsearch functionality like Laravel Eloquent models.

11222.9k](/packages/isswp101-elasticsearch-eloquent)[matchory/elasticsearch

The missing elasticsearch ORM for Laravel!

3064.0k](/packages/matchory-elasticsearch)

PHPackages © 2026

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