Skip to content

devemio/elasticsearch-eloquent

Repository files navigation

Elasticsearch Eloquent 2.x

Latest Version on Packagist Software License Build Status Coverage Status Quality Score Total Downloads

This package allows you to interact with Elasticsearch as you interact with Eloquent models in Laravel.

Requirements

  • PHP >= 8.0
  • Elasticsearch >= 7.0

Install

Via Composer

$ composer require isswp101/elasticsearch-eloquent

Usage

Create a new model

You should override index and type properties to determine the document path.

use Isswp101\Persimmon\Models\BaseElasticsearchModel;
use Isswp101\Persimmon\Persistence\Persistence;
use Isswp101\Persimmon\Contracts\PersistenceContract;

class Product extends BaseElasticsearchModel
{
    protected string $index = 'index';
    protected string|null $type = 'type'; // optional

    // If you have a pre-configured Elasticsearch client you can pass it here (optional)
    public function createPersistence(): PersistenceContract
    {
        return new Persistence($client);
    }
}

Use the static create() method to create the document in Elasticsearch:

$product = Product::create([
    'id' => 1, 
    'name' => 'Product',
    'price' => 10
]);

Save the model

$product = new Product();
$product->id = 1;
$product->name = 'Product';
$product->price = 10;
$product->save();

Use save() method to store model data in Elasticsearch. Let's see how this looks in Elasticsearch:

{
   "_index": "index",
   "_type": "type",
   "_id": "1",
   "_version": 1,
   "_source": {
      "id": 1,
      "name": "Product",
      "price": 10,
      "created_at": "2021-03-27T11:24:15+00:00",
      "updated_at": "2021-03-27T11:24:15+00:00"
   }
}

Fields created_at and updated_at were created automatically.

Find existing model

$product = Product::find(1);

If you have big data in Elasticsearch you can specify certain fields to retrieve:

$product = Product::find(1, ['name']);

There are the following methods:

  • findOrFail() returns ModelNotFoundException exception if no result found.

Cache

There is a smart model cache when you use methods like find(), findOrFail() and so on.

$product = Product::find(1, ['name']);  // from elasticsearch
$product = Product::find(1, ['name']);  // from cache
$product = Product::find(1, ['price']); // from elasticsearch
$product = Product::find(1, ['price']); // from cache
$product = Product::find(1, ['name']);  // from cache
$product = Product::find(1);            // from elasticsearch
$product = Product::find(1);            // from cache
$product = Product::find(1, ['name']);  // from cache
$product = Product::find(1, ['price']); // from cache

Partial update

You can use the partial update to update specific fields quickly.

$product = Product::find(1, ['name']);
$product->name = 'Name';
$product->save(['name']);

Delete models

$product = Product::find(1);
$product->delete();

You can use the static method:

Product::destroy(1);

Model events

Out of the box you are provided with a simple implementation of events.
You can override the following methods to define events:

  • saving() is called before saving, updating, creating the model
  • saved() is called after saving, updating, creating the model
  • deleting() is called before deleting the model
  • deleted() is called after deleting the model
  • searching() is called after searching models
  • searched() is called after searching models

For example:

use Isswp101\Persimmon\Models\BaseElasticsearchModel;

class Product extends BaseElasticsearchModel
{
    protected function saving(): bool
    {
        // Disable update if it's free
        return $this->price <= 0;
    }

    protected function deleting(): bool
    {
        if ($this->user_id != 1) {
            throw new DomainException('No permissions to delete this model');
        }

        return true;
    }
}

Basic search

There are helpers to search documents:

The first($query) method returns the first document according to the query or null.

$product = Product::first($query);

The firstOrFail($query) method returns ModelNotFoundException exception if first($query) returns null.

$product = Product::firstOrFail($query);

The search($query) method returns documents according to the query.

$products = Product::search($query);

The all($query) method returns all documents (default 50 items per request) according to the query.

$products = Product::all($query);

If $query is not passed the query will be as match_all query.

Query Builder

Consider using these packages:

Testing

$ composer test

License

The MIT License (MIT).