PHPackages                             skvn/plastic - 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. skvn/plastic

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

skvn/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.

v0.5.3(8y ago)06MITPHPPHP &gt;=7.0

Since Jun 14Pushed 7y ago2 watchersCompare

[ Source](https://github.com/skvn/plastic)[ Packagist](https://packagist.org/packages/skvn/plastic)[ Docs](https://github.com/sleimanx2/plastic)[ RSS](/packages/skvn-plastic/feed)WikiDiscussions master Synced 3d ago

READMEChangelogDependencies (11)Versions (26)Used By (0)

[![Plastic Logo](https://camo.githubusercontent.com/2d0c41adb7881bb9c38f4fe8d2c54a31ef05ec52102cf7afd8be0ec45ecbf2e5/687474703a2f2f692e696d6775722e636f6d2f50796f6c5937672e706e67)](https://camo.githubusercontent.com/2d0c41adb7881bb9c38f4fe8d2c54a31ef05ec52102cf7afd8be0ec45ecbf2e5/687474703a2f2f692e696d6775722e636f6d2f50796f6c5937672e706e67)

> 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.

[![License](https://camo.githubusercontent.com/f45d904953153ca304a2328243d2733e095eee13a631a1f390709885d41dd692/68747470733a2f2f706f7365722e707567782e6f72672f6c61726176656c2f6672616d65776f726b2f6c6963656e73652e737667)](https://packagist.org/packages/sleimanx2/plastic) [![Build Status](https://camo.githubusercontent.com/7f05066747dc89dc2a671241f0e8a978e11e06b27a9792c61de680cfbd6c82f8/68747470733a2f2f7472617669732d63692e6f72672f736c65696d616e78322f706c61737469632e7376673f6272616e63683d6d61737465722626726566726573683d32)](https://travis-ci.org/sleimanx2/plastic) [![StyleCI](https://camo.githubusercontent.com/a0a9308a3199234b50ee5791b94b70b86841ff8a2502cfa709a24e51650d052c/68747470733a2f2f7374796c6563692e696f2f7265706f732f35383236343339352f736869656c64)](https://styleci.io/repos/58264395)

> This package is still under active development and may change.

> For Elasticsearch v2 please refer to version &lt; 0.4.0.

Installing Plastic
==================

[](#installing-plastic)

```
composer require sleimanx2/plastic
```

If you are using **Laravel &gt;=5.5** the service provider will be **automatically discovered** otherwise we need to add the plastic service provider to `config/app.php` under the providers key:

```
Sleimanx2\Plastic\PlasticServiceProvider::class
```

Finally we need to run:

```
php artisan vendor:publish
```

This will create a config file at `config/plastic.php` and a mapping directory at `database/mappings`.

Usage
=====

[](#usage)

- [Defining Searchable Models](#searchable-models)
- [Storing Model Content](#store-content)
- [Searching](#searching)
- [Aggregation](#aggregation)
- [Suggestions](#suggestions)
- [Mappings](#mappings)
- [Populate An Index](#populate-an-index)
- [Access The Client](#access-client)

Defining Searchable Models
-----------------------------------------

[](#defining-searchable-models)

To get started, enable searching capabilities in your model by adding the `Sleimanx2\Plastic\Searchable` trait:

```
use Sleimanx2\Plastic\Searchable;

class Book extends Model
{
    use Searchable;
}
```

### Defining what data to store.

[](#defining-what-data-to-store)

By default, Plastic will store all visible properties of your model, using `$model->toArray()`.

In addition, Plastic provides you with two ways to manually specify which attributes/relations should be stored in Elasticsearch.

#### 1 - Providing a searchable property to our model

[](#1---providing-a-searchable-property-to-our-model)

```
public $searchable = ['id', 'name', 'body', 'tags', 'images'];
```

#### 2 - Providing a buildDocument method

[](#2---providing-a-builddocument-method)

```
public function buildDocument()
{
    return [
        'id' => $this->id,
        'tags' => $this->tags
    ];
}
```

### Custom elastic type name

[](#custom-elastic-type-name)

By the default Plastic will use the model table name as the model type. You can customize it by adding a `$documentType` property to your model:

```
public $documentType = 'custom_type';
```

### Custom elastic index name

[](#custom-elastic-index-name)

By the default Plastic will use the index defined in the configuration file. You can customize in which index your model data will be stored by setting the `$documentIndex` property to your model:

```
public $documentIndex = 'custom_index';
```

Storing Model Content
------------------------------------

[](#storing-model-content)

Plastic automatically syncs model data with elastic when you save or delete your model from our SQL DB, however this feature can be disabled by adding `public $syncDocument = false` to your model.

> Its important to note that manual document update should be performed in multiple scenarios:

> 1 - When you perform a bulk update or delete, no Eloquent event is triggered, therefore the document data won't be synced.

> 2 - Plastic doesn't listen to related models events (yet), so when you update a related model's content you should consider updating the parent document.

### Saving a document

[](#saving-a-document)

```
$book = Book::first()->document()->save();
```

### Partial updating a document

[](#partial-updating-a-document)

```
$book = Book::first()->document()->update();
```

### Deleting a document

[](#deleting-a-document)

```
$book = Book::first()->document()->delete();
```

### Saving documents in bulk

[](#saving-documents-in-bulk)

```
Plastic::persist()->bulkSave(Tag::find(1)->books);
```

### Deleting documents in bulk

[](#deleting-documents-in-bulk)

```
$authors = Author::where('age','>',25)->get();

Plastic::persist()->bulkDelete($authors);
```

Searching Model Content
--------------------------------------

[](#searching-model-content)

Plastic provides a fluent syntax to query Elasticsearch which leads to compact readable code. Lets dig into it:

```
$result = Book::search()->match('title','pulp')->get();

// Returns a collection of Book Models
$books = $result->hits();

// Returns the total number of matched documents
$result->totalHits();

// Returns the highest query score
$result->maxScore();

//Returns the time needed to execute the query
$result->took();
```

To get the raw DSL query that will be executed you can call `toDSL()`:

```
$dsl = Book::search()->match('title','pulp')->toDSL();
```

### Pagination

[](#pagination)

```
$books = Book::search()
    ->multiMatch(['title', 'description'], 'ham on rye', ['fuzziness' => 'AUTO'])
    ->sortBy('date')
    ->paginate();
```

You can still access the result object after pagination using the result method:

```
$books->result();
```

### Bool Query

[](#bool-query)

```
User::search()
    ->must()
        ->term('name','kimchy')
    ->mustNot()
        ->range('age',['from'=>10,'to'=>20])
    ->should()
        ->match('bio','developer')
        ->match('bio','elastic')
    ->filter()
        ->term('tag','tech')
    ->get();
```

### Nested Query

[](#nested-query)

```
$contain = 'foo';

Post::search()
    ->multiMatch(['title', 'body'], $contain)
    ->nested('tags', function (SearchBuilder $builder) use ($contain) {
        $builder->match('tags.name', $contain);
    })->get();
```

> Check out this [documentation](docs/search.md) of supported search queries within Plastic and how to apply unsupported queries.

### Change index on the fly

[](#change-index-on-the-fly)

To switch to a different index for a single query, simply use the `index` method.

```
$result = Book::search()->index('special-books')->match('title','pulp')->get();
```

Aggregation
--------------------------

[](#aggregation)

```
$result = User::search()
    ->match('bio', 'elastic')
    ->aggregate(function (AggregationBuilder $builder) {
        $builder->average('average_age', 'age');
    })->get();

$aggregations = $result->aggregations();
```

> Check out this [documentation](docs/aggregation.md) of supported aggregations within plastic and how to apply unsupported aggregations.

Suggestions
--------------------------

[](#suggestions)

```
Plastic::suggest()->completion('tag_suggest', 'photo')->get();
```

The suggestions query builder can also be accessed directly from the model as well:

```
//this be handy if you have a custom index for your model
Tag::suggest()->term('tag_term','admin')->get();
```

Model Mapping
----------------------------

[](#model-mapping)

Mappings are an important aspect of Elasticsearch. You can compare them to indexing in SQL databases. Mapping your models yields better and more efficient search results, and allows us to use some special query functions like nested fields and suggestions.

### Generate a Model Mapping

[](#generate-a-model-mapping)

```
php artisan make:mapping "App\User"
```

The new mapping will be placed in your `database/mappings` directory.

### Mapping Structure

[](#mapping-structure)

A mapping class contains a single method `map`. The map method is used to map the given model fields.

Within the `map` method you may use the Plastic Map builder to expressively create field maps. For example, let's look at a sample mapping that creates a Tag model map:

```
use Sleimanx2\Plastic\Map\Blueprint;
use Sleimanx2\Plastic\Mappings\Mapping;

class AppTag extends Mapping
{
    /**
     * Full name of the model that should be mapped
     *
     * @var string
     */
    protected $model = App\Tag::class;

    /**
     * Run the mapping.
     *
     * @return void
     */
    public function map()
    {
        Map::create($this->getModelType(), function (Blueprint $map) {
            $map->string('name')->store('true')->index('analyzed');

            // instead of the fluent syntax we can use the second method argument to fill the attributes
            $map->completion('suggestion', ['analyzer' => 'simple', 'search_analyzer' => 'simple']);
        },$this->getModelIndex());
    }
}
```

> To learn about all of the methods available on the Map builder, check out this [documentation](docs/mapping.md).

### Run Mappings

[](#run-mappings)

Running the created mappings can be done using the Artisan console command:

```
php artisan mapping:run
```

### Updating Mappings

[](#updating-mappings)

If your update consists only of adding a new field mapping you can always update our model map with your new field and run:

```
php artisan mapping:rerun
```

The mapping for existing fields cannot be updated or deleted, so you'll need to use one of following techniques to update existing fields.

#### 1 - Create a new index

[](#1---create-a-new-index)

You can always create a new Elasticsearch index and re-run the mappings. After running the mappings you can use the `bulkSave` method to sync your SQL data with Elasticsearch.

#### 2 - Using aliases

[](#2---using-aliases)

Its recommended to create your Elasticsearch index with an alias to ease the process of updating your model mappings with zero downtime. To learn more check out:

Populate An Index
--------------------------------

[](#populate-an-index)

Populating an index with searchable models can be done by running an Artisan console command :

```
php artisan plastic:populate [--mappings][--index=...][--database=...]
```

- `--mappings` Create the models mappings before populating the index
- `--database=...` Database connection to use for mappings instead of the default one
- `--index=...` Index to populate instead of the default one

The list of models from which to recreate the documents has to be configured **per index** in `config/plastic.php`:

```
    'populate' => [
        'models' => [
            // Models for the default index
            env('PLASTIC_INDEX', 'plastic') => [
                App\Models\Article::class,
                App\Models\Page::class,
            ],
            // Models for the index "another_index"
            'another_index' => [
                App\Models\User::class,
            ],
        ],
    ],

```

Access The Client
--------------------------------

[](#access-the-client)

You can access the Elasticsearch client to manage your indices and aliases as follows:

```
$client = Plastic::getClient();

//index delete
$client->indices()->delete(['index'=> Plastic::getDefaultIndex()]);
//index create
$client->indices()->create(['index' => Plastic::getDefaultIndex()]);
```

More about the official elastic client :

Contributing
============

[](#contributing)

Thank you for contributing, The contribution guide can be found [Here](CONTRIBUTING.md).

License
=======

[](#license)

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

To Do
=====

[](#to-do)

Search Query Builder
--------------------

[](#search-query-builder)

- implement Boosting query
- implement ConstantScore query
- implement DisMaxQuery query
- implement MoreLikeThis query (with raw eloquent models)
- implement GeoShape query

Aggregation Query Builder
-------------------------

[](#aggregation-query-builder)

- implement Nested aggregation
- implement ExtendedStats aggregation
- implement TopHits aggregation

Mapping
-------

[](#mapping)

- Find a seamless way to update field mappings with zero downtime with aliases

General
-------

[](#general)

- Better query builder documentation

###  Health Score

26

—

LowBetter than 43% of packages

Maintenance20

Infrequent updates — may be unmaintained

Popularity4

Limited adoption so far

Community19

Small or concentrated contributor base

Maturity58

Maturing project, gaining track record

 Bus Factor1

Top contributor holds 72.1% 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 ~28 days

Recently: every ~50 days

Total

24

Last Release

2958d ago

PHP version history (3 changes)v0.1.0PHP &gt;=5.5.9

v0.2.6PHP &gt;=5.6.4

v0.5.0PHP &gt;=7.0

### Community

Maintainers

![](https://www.gravatar.com/avatar/5f2a402c3534f081da8051ce42320a03b860f4b40d19767538e2649223eef2f4?d=identicon)[skvn](/maintainers/skvn)

---

Top Contributors

[![sleimanx2](https://avatars.githubusercontent.com/u/5547347?v=4)](https://github.com/sleimanx2 "sleimanx2 (178 commits)")[![killtw](https://avatars.githubusercontent.com/u/1076225?v=4)](https://github.com/killtw "killtw (13 commits)")[![shaoshiva](https://avatars.githubusercontent.com/u/2183266?v=4)](https://github.com/shaoshiva "shaoshiva (10 commits)")[![mxp100](https://avatars.githubusercontent.com/u/8124083?v=4)](https://github.com/mxp100 "mxp100 (9 commits)")[![helloiamlukas](https://avatars.githubusercontent.com/u/15997450?v=4)](https://github.com/helloiamlukas "helloiamlukas (8 commits)")[![jamesgraham](https://avatars.githubusercontent.com/u/934542?v=4)](https://github.com/jamesgraham "jamesgraham (5 commits)")[![ellisio](https://avatars.githubusercontent.com/u/127468?v=4)](https://github.com/ellisio "ellisio (4 commits)")[![tobias-kuendig](https://avatars.githubusercontent.com/u/8600029?v=4)](https://github.com/tobias-kuendig "tobias-kuendig (4 commits)")[![atodd](https://avatars.githubusercontent.com/u/1340568?v=4)](https://github.com/atodd "atodd (2 commits)")[![reynotech](https://avatars.githubusercontent.com/u/24636036?v=4)](https://github.com/reynotech "reynotech (2 commits)")[![sgtpepper9907](https://avatars.githubusercontent.com/u/21094671?v=4)](https://github.com/sgtpepper9907 "sgtpepper9907 (2 commits)")[![mschreck](https://avatars.githubusercontent.com/u/10470505?v=4)](https://github.com/mschreck "mschreck (1 commits)")[![henriquebremenkanp](https://avatars.githubusercontent.com/u/3855603?v=4)](https://github.com/henriquebremenkanp "henriquebremenkanp (1 commits)")[![bjrnblm](https://avatars.githubusercontent.com/u/2300511?v=4)](https://github.com/bjrnblm "bjrnblm (1 commits)")[![SergeySetti](https://avatars.githubusercontent.com/u/9052420?v=4)](https://github.com/SergeySetti "SergeySetti (1 commits)")[![zhwei](https://avatars.githubusercontent.com/u/1446459?v=4)](https://github.com/zhwei "zhwei (1 commits)")[![daverdalas](https://avatars.githubusercontent.com/u/5399813?v=4)](https://github.com/daverdalas "daverdalas (1 commits)")[![chellman](https://avatars.githubusercontent.com/u/934603?v=4)](https://github.com/chellman "chellman (1 commits)")[![svkc](https://avatars.githubusercontent.com/u/16741833?v=4)](https://github.com/svkc "svkc (1 commits)")[![JFossey](https://avatars.githubusercontent.com/u/4981545?v=4)](https://github.com/JFossey "JFossey (1 commits)")

---

Tags

laravelelasticsearchmodeleloquentelasticmapperodm

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/skvn-plastic/health.svg)

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

###  Alternatives

[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.

508141.9k1](/packages/sleimanx2-plastic)[pdphilip/elasticsearch

An Elasticsearch implementation of Laravel's Eloquent ORM

145360.2k4](/packages/pdphilip-elasticsearch)[tucker-eric/eloquentfilter

An Eloquent way to filter Eloquent Models

1.8k4.8M26](/packages/tucker-eric-eloquentfilter)[mongodb/laravel-mongodb

A MongoDB based Eloquent model and Query builder for Laravel

7.1k7.2M71](/packages/mongodb-laravel-mongodb)[dyrynda/laravel-model-uuid

This package allows you to easily work with UUIDs in your Laravel models.

4802.8M8](/packages/dyrynda-laravel-model-uuid)[laravel-doctrine/orm

An integration library for Laravel and Doctrine ORM

8425.3M87](/packages/laravel-doctrine-orm)

PHPackages © 2026

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