PHPackages                             fereydooni/laravel-elastoquent - 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. fereydooni/laravel-elastoquent

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

fereydooni/laravel-elastoquent
==============================

A robust Elasticsearch ORM for Laravel, mirroring Eloquent functionality

02PHPCI failing

Since Apr 24Pushed 1y ago1 watchersCompare

[ Source](https://github.com/Behnamfe76/laravel-elastoquent)[ Packagist](https://packagist.org/packages/fereydooni/laravel-elastoquent)[ RSS](/packages/fereydooni-laravel-elastoquent/feed)WikiDiscussions master Synced 1mo ago

READMEChangelog (1)DependenciesVersions (1)Used By (0)

Laravel Elastoquent
===================

[](#laravel-elastoquent)

A robust Elasticsearch ORM for Laravel, mirroring Eloquent functionality. This package provides a familiar Eloquent-like API for indexing, querying, and managing data in Elasticsearch.

Requirements
------------

[](#requirements)

- PHP 8.1+
- Laravel 10.x+
- Elasticsearch 8.x

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

[](#installation)

```
composer require fereydooni/laravel-elastoquent
```

### Publish Configuration

[](#publish-configuration)

```
php artisan vendor:publish --provider="Fereydooni\LaravelElastoquent\ElasticORMServiceProvider"
```

### Run Migrations

[](#run-migrations)

```
php artisan migrate
```

Configuration
-------------

[](#configuration)

The package configuration is located at `config/elastic-orm.php`. Key options include:

```
return [
    // Elasticsearch connection settings
    'connection' => [
        'hosts' => ['localhost:9200'],
        'username' => env('ELASTIC_USERNAME', null),
        'password' => env('ELASTIC_PASSWORD', null),
    ],

    // Default index prefix for all indices
    'index_prefix' => env('ELASTIC_INDEX_PREFIX', 'app_'),

    // Enable/disable soft deletes
    'soft_deletes' => true,

    // Bulk indexing batch size
    'bulk_size' => 1000,
];
```

Basic Usage
-----------

[](#basic-usage)

### Define a Model

[](#define-a-model)

```
use Fereydooni\LaravelElastoquent\Attributes\ElasticModel;
use Fereydooni\LaravelElastoquent\Attributes\ElasticField;
use Fereydooni\LaravelElastoquent\Models\Model;

#[ElasticModel(index: 'users', settings: ['number_of_shards' => 1])]
class User extends Model
{
    #[ElasticField(type: 'text', index: true)]
    public string $name;

    #[ElasticField(type: 'keyword')]
    public string $email;

    public function posts()
    {
        return $this->hasMany(Post::class, 'user_id');
    }
}
```

### CRUD Operations

[](#crud-operations)

```
// Create a user
$user = User::create([
    'name' => 'John Doe',
    'email' => 'john@example.com',
]);

// Find a user
$user = User::find('user_id');

// Update a user
$user->name = 'Jane Doe';
$user->save();

// Delete a user
$user->delete();
```

### Query Builder

[](#query-builder)

```
// Basic where clause
$users = User::where('name', 'John')->get();

// Advanced query
$users = User::where('name', 'like', 'J*')
    ->orWhere('email', 'contains', 'example.com')
    ->orderBy('name', 'asc')
    ->limit(10)
    ->get();

// Pagination
$users = User::where('active', true)
    ->paginate(15);
```

### Full-Text Search

[](#full-text-search)

```
// Simple search
$results = User::search('John Doe')->get();

// Advanced search with filters
$results = User::search('John')
    ->filter('active', true)
    ->get();
```

### Advanced Elasticsearch Features

[](#advanced-elasticsearch-features)

#### Vector Search

[](#vector-search)

```
// Define a model with vector fields
#[ElasticModel(index: 'documents')]
class Document extends Model
{
    #[ElasticField(type: 'dense_vector', options: ['dims' => 768])]
    public array $embedding;

    #[ElasticField(type: 'text')]
    public string $content;
}

// Perform KNN vector search
$results = Document::query()
    ->vectorSearch('embedding', $queryVector, k: 10)
    ->get();
```

#### Semantic Search

[](#semantic-search)

```
// Using embedding services (OpenAI, HuggingFace, etc.)
$results = Document::query()
    ->semanticSearch(
        "What is machine learning?",
        'embedding',
        'openai'
    )
    ->get();

// Sparse vector search with ELSER
$results = Document::query()
    ->sparseVectorSearch("How does AI work?", 'content_embedding')
    ->get();
```

#### Hybrid Search &amp; Semantic Reranking

[](#hybrid-search--semantic-reranking)

```
// Hybrid search combining text and vector scores
$results = Document::query()
    ->hybridSearch(
        "machine learning applications",
        ['content'],
        'embedding',
        $queryVector,
        textWeight: 0.3,
        vectorWeight: 0.7
    )
    ->get();

// Semantic reranking to improve relevance
$results = Document::query()
    ->search("artificial intelligence")
    ->semanticRerank("How do neural networks work?")
    ->get();
```

#### ES|QL Support

[](#esql-support)

```
// Using Elasticsearch's SQL-like query language
$results = Document::query()
    ->esql("FROM documents WHERE match(content, 'artificial intelligence') | LIMIT 10")
    ->get();
```

#### Performance Optimizations

[](#performance-optimizations)

```
// Field selection and exclusion
$results = Document::query()
    ->select(['content', 'title'])    // Only return these fields
    ->exclude(['embedding'])          // Exclude large vector fields
    ->trackTotalHits(false)           // Disable exact hit counting for better performance
    ->search("machine learning")
    ->get();
```

### Data Transfer Objects &amp; Pagination

[](#data-transfer-objects--pagination)

Laravel Elastoquent integrates with [spatie/laravel-data](https://github.com/spatie/laravel-data) to provide structured DTOs for your Elasticsearch results:

```
// Using the built-in ElasticDocument DTO
$results = Document::query()
    ->where('category', 'technology')
    ->asDocument()  // Return results as ElasticDocument DTOs
    ->get();

// Using a custom DTO that extends ElasticDocument
class ProductDocument extends ElasticDocument
{
    public function getFormattedPrice(): string
    {
        return '$' . number_format($this->field('price', 0), 2);
    }
}

$results = Product::query()
    ->asData(ProductDocument::class)  // Use custom DTOs
    ->get();

// Enhanced pagination with DTOs
$paginatedResults = Product::query()
    ->where('active', true)
    ->asDocument()
    ->paginate(15);

// Accessing pagination metadata
echo "Showing {$paginatedResults->count()} of {$paginatedResults->total()} results";
echo "Page {$paginatedResults->currentPage()} of {$paginatedResults->lastPage()}";

// Converting to Spatie Data collection
use Spatie\LaravelData\Data;

class ProductData extends Data
{
    public function __construct(
        public string $id,
        public string $name,
        public float $price,
    ) {}

    // Transform from ElasticDocument to Spatie Data
    public static function fromElasticDocument(ElasticDocument $doc): self
    {
        return new self(
            id: $doc->id,
            name: $doc->field('name'),
            price: (float)$doc->field('price', 0)
        );
    }
}

// Map the results to Spatie Data objects
$dataCollection = $results->map(fn($doc) => ProductData::fromElasticDocument($doc));
```

### Retriever API Support

[](#retriever-api-support)

```
// Using retrievers for advanced semantic search
$results = Document::query()
    ->retriever(
        "How does machine learning work?",
        ['content'],
        'hybrid'  // Use hybrid retrieval (text + semantic)
    )
    ->get();
```

### Relationships

[](#relationships)

```
// Define relationships
class User extends Model
{
    public function posts()
    {
        return $this->hasMany(Post::class, 'user_id');
    }
}

class Post extends Model
{
    public function user()
    {
        return $this->belongsTo(User::class, 'user_id');
    }
}

// Using relationships
$user = User::find('user_id');
$posts = $user->posts()->get();

// Eager loading
$users = User::with('posts')->get();
```

### Bulk Operations

[](#bulk-operations)

```
// Bulk create
User::bulkIndex([
    ['name' => 'Jane Doe', 'email' => 'jane@example.com'],
    ['name' => 'Bob Smith', 'email' => 'bob@example.com'],
]);
```

User Model Example
------------------

[](#user-model-example)

Here's an example of how to use the User model with Elasticsearch and Spatie Data:

```
use Fereydooni\LaravelElastoquent\Examples\Models\User;
use Fereydooni\LaravelElastoquent\Examples\Models\UserData;

// Create a new user
$user = new User([
    'name' => 'John Doe',
    'email' => 'john@example.com',
    'password' => 'hashed_password',
    'age' => 30,
    'is_active' => true,
    'roles' => ['user', 'admin'],
    'profile' => [
        'bio' => 'Software Developer',
        'location' => 'New York',
        'website' => 'https://example.com',
        'avatar' => 'https://example.com/avatar.jpg'
    ]
]);

// Save the user to Elasticsearch
$user->save();

// Find a user by ID
$user = User::find('user_id');

// Update user attributes
$user->setName('Jane Doe');
$user->setAge(31);
$user->save();

// Delete a user
$user->delete();

// Query users
$activeUsers = User::where('is_active', true)
    ->where('age', '>', 25)
    ->get();

// Convert to Spatie Data DTO
$userData = $user->toData();

// Use DTO in API responses
return response()->json($userData->toArray());

// Or use Spatie Data's collection
$usersData = $activeUsers->map(fn($user) => $user->toData());
return response()->json($usersData->toArray());
```

### Available Query Methods

[](#available-query-methods)

The User model supports all standard Eloquent-like query methods:

```
// Basic queries
User::all();
User::find('id');
User::first();
User::where('age', '>', 25)->get();

// Pagination
User::paginate(15);
User::simplePaginate(15);
User::cursorPaginate(15);

// Aggregations
User::where('is_active', true)->count();
User::where('age', '>', 25)->exists();

// Nested queries
User::where('profile.location', 'New York')->get();

// Sorting
User::orderBy('created_at', 'desc')->get();

// Limiting
User::limit(10)->get();
User::offset(5)->limit(10)->get();
```

### Elasticsearch Features

[](#elasticsearch-features)

The User model includes several Elasticsearch-specific features:

1. **Nested Fields**: The `profile` field is defined as a nested type, allowing for complex queries on nested objects.
2. **Field Types**:

    - `text` for full-text search (name, profile.bio)
    - `keyword` for exact matches (email, roles)
    - `integer` for numeric values (age)
    - `boolean` for true/false values (is\_active)
    - `date` for timestamps (created\_at, updated\_at)
3. **Index Settings**:

    - Single shard for consistent ordering
    - One replica for high availability
4. **Mapping**:

    - Custom field mappings for optimal search performance
    - Nested object support for complex data structures
5. **Spatie Data Integration**:

    - Automatic snake\_case to camelCase conversion
    - Type-safe data transfer objects
    - Built-in validation and transformation
    - Easy serialization to JSON

Contributing
------------

[](#contributing)

Contributions are welcome! Please feel free to submit a Pull Request.

License
-------

[](#license)

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

###  Health Score

15

—

LowBetter than 3% of packages

Maintenance36

Infrequent updates — may be unmaintained

Popularity2

Limited adoption so far

Community7

Small or concentrated contributor base

Maturity15

Early-stage or recently created project

 Bus Factor1

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

### Community

Maintainers

![](https://www.gravatar.com/avatar/d9ae6dcf5d71a4eda508bc3b84bc78470548ebd7ed1824f3c194e03fd6815bfb?d=identicon)[Behnamfe76](/maintainers/Behnamfe76)

---

Top Contributors

[![Behnamfe76](https://avatars.githubusercontent.com/u/101217538?v=4)](https://github.com/Behnamfe76 "Behnamfe76 (28 commits)")

### Embed Badge

![Health badge](/badges/fereydooni-laravel-elastoquent/health.svg)

```
[![Health](https://phpackages.com/badges/fereydooni-laravel-elastoquent/health.svg)](https://phpackages.com/packages/fereydooni-laravel-elastoquent)
```

###  Alternatives

[doctrine/orm

Object-Relational-Mapper for PHP

10.2k285.3M6.2k](/packages/doctrine-orm)[jdorn/sql-formatter

a PHP SQL highlighting library

3.9k115.1M102](/packages/jdorn-sql-formatter)[illuminate/database

The Illuminate Database package.

2.8k52.4M9.4k](/packages/illuminate-database)[mongodb/mongodb

MongoDB driver library

1.6k64.0M546](/packages/mongodb-mongodb)[ramsey/uuid-doctrine

Use ramsey/uuid as a Doctrine field type.

90340.3M211](/packages/ramsey-uuid-doctrine)[reliese/laravel

Reliese Components for Laravel Framework code generation.

1.7k3.4M16](/packages/reliese-laravel)

PHPackages © 2026

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