PHPackages                             devilsberg/laravel-mariadb-vector - 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. devilsberg/laravel-mariadb-vector

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

devilsberg/laravel-mariadb-vector
=================================

MariaDB 11.7+ native vector storage and search for Laravel Eloquent models

v1.2.0(3mo ago)127↑70%MITPHPPHP ^8.4CI passing

Since Mar 24Pushed 2mo agoCompare

[ Source](https://github.com/erik-ros-devilsberg/laravel-mariadb-vector)[ Packagist](https://packagist.org/packages/devilsberg/laravel-mariadb-vector)[ RSS](/packages/devilsberg-laravel-mariadb-vector/feed)WikiDiscussions main Synced 3w ago

READMEChangelogDependencies (8)Versions (4)Used By (0)

Laravel MariaDB Vector
======================

[](#laravel-mariadb-vector)

[![Latest Version on Packagist](https://camo.githubusercontent.com/cebd03a5b71be57392650e4bc0094fbcc93a578c31da2e8ba8c36bc60bdffde1/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f762f646576696c73626572672f6c61726176656c2d6d6172696164622d766563746f722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/devilsberg/laravel-mariadb-vector)[![Tests](https://camo.githubusercontent.com/b5bb7ec02fb37f2840b7a21646ea185f61389ad4e75ecbfeaf7313326c5e66aa/68747470733a2f2f696d672e736869656c64732e696f2f6769746875622f616374696f6e732f776f726b666c6f772f7374617475732f6572696b2d726f732d646576696c73626572672f6c61726176656c2d6d6172696164622d766563746f722f74657374732e796d6c3f6272616e63683d6d61696e266c6162656c3d7465737473267374796c653d666c61742d737175617265)](https://github.com/erik-ros-devilsberg/laravel-mariadb-vector/actions/workflows/tests.yml)[![License](https://camo.githubusercontent.com/17b654eca9e0061ae9a446191285a8e09733b6c1b5827b88e0bbf73b7c22fdf2/68747470733a2f2f696d672e736869656c64732e696f2f7061636b61676973742f6c2f646576696c73626572672f6c61726176656c2d6d6172696164622d766563746f722e7376673f7374796c653d666c61742d737175617265)](https://packagist.org/packages/devilsberg/laravel-mariadb-vector)[![Ko-fi](https://camo.githubusercontent.com/5aecf0653384af4e61e0ffb78afd6d262d3fb18625af7a2dd3fcddfce2027eec/68747470733a2f2f696d672e736869656c64732e696f2f62616467652f737570706f72742d6b6f2d2d66692d4646354535423f7374796c653d666c61742d737175617265266c6f676f3d6b6f2d6669266c6f676f436f6c6f723d7768697465)](https://ko-fi.com/devilsberg)

MariaDB 11.7+ native vector storage and search for Laravel.

This package brings vector column support, binary-safe casting, and similarity search macros to Eloquent — powered by MariaDB's native `VECTOR` type and `VEC_DISTANCE_*` functions. Think of it as the MariaDB equivalent of pgvector for Laravel.

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

[](#requirements)

- PHP 8.4+
- Laravel 12+
- MariaDB 11.7+

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

[](#installation)

```
composer require devilsberg/laravel-mariadb-vector
```

Publish the config file:

```
php artisan vendor:publish --tag=mariadb-vector-config
```

Quick Start
-----------

[](#quick-start)

### 1. Create a migration

[](#1-create-a-migration)

```
Schema::create('articles', function (Blueprint $table) {
    $table->id();
    $table->string('title');
    $table->text('body');
    $table->vector('embedding', 768);
    $table->vectorIndex('embedding'); // enables fast ANN search
    $table->timestamps();
});
```

### 2. Set up your model

[](#2-set-up-your-model)

```
use Devilsberg\LaravelMariadbVector\Casts\VectorCast;

class Article extends Model
{
    protected function casts(): array
    {
        return [
            'embedding' => VectorCast::class,
        ];
    }
}
```

### 3. Store a vector

[](#3-store-a-vector)

```
$embedding = $yourEmbeddingProvider->embed($article->body); // your code

$article->embedding = $embedding; // float array, e.g. [0.1, 0.2, ...]
$article->save();
```

### 4. Search by similarity

[](#4-search-by-similarity)

```
use Devilsberg\LaravelMariadbVector\Distance;

$queryVector = $yourEmbeddingProvider->embed('climate change effects');

$results = Article::query()
    ->nearestNeighbors('embedding', $queryVector, Distance::Cosine)
    ->limit(10)
    ->get();

// Each result has a `score` column — higher is more similar (0–1)
foreach ($results as $article) {
    echo $article->title . ' — ' . $article->score;
}
```

Vector Indexes
--------------

[](#vector-indexes)

Without a vector index every similarity search performs a full table scan — fine for thousands of rows, slow at scale. MariaDB 11.7 supports `VECTOR INDEX` for approximate nearest neighbor (ANN) lookups, exposed via the standard `vectorIndex()` Blueprint method that Laravel 12 provides.

### Adding an index in a migration

[](#adding-an-index-in-a-migration)

```
Schema::create('articles', function (Blueprint $table) {
    $table->id();
    $table->vector('embedding', 768);
    $table->vectorIndex('embedding'); // ALTER TABLE ... ADD VECTOR INDEX runs after CREATE TABLE
    $table->timestamps();
});
```

### Custom index name

[](#custom-index-name)

By default the index name follows Laravel's standard index naming — `{table}_{column}_vectorindex`:

```
$table->vectorIndex('embedding');                       // → articles_embedding_vectorindex
$table->vectorIndex('embedding', 'articles_vec_idx');   // → articles_vec_idx (custom)
```

### Adding an index to an existing table

[](#adding-an-index-to-an-existing-table)

```
Schema::table('articles', function (Blueprint $table) {
    $table->vectorIndex('embedding');
});
```

> **Note:** MariaDB requires the vector column to be `NOT NULL` to add a vector index. Attempting to index a nullable vector column will raise a database error.
>
> **Note:** MariaDB 11.7 supports only **one** `VECTOR INDEX` per table. Attempting to add a second one will raise a database error.

Bring Your Own Embeddings
-------------------------

[](#bring-your-own-embeddings)

This package handles **storage and search** only. You generate embeddings however you want — Ollama, Mistral, Cohere, a local Python model, or anything that produces a float array.

```
// Ollama (local)
$response = Http::post('http://localhost:11434/api/embed', [
    'model' => 'nomic-embed-text',
    'input' => $text,
]);
$embedding = $response->json('embeddings.0');

// Mistral
$response = Http::withToken(config('services.mistral.key'))
    ->post('https://api.mistral.ai/v1/embeddings', [
        'model' => 'mistral-embed',
        'input' => [$text],
    ]);
$embedding = $response->json('data.0.embedding');

// Any source — just pass a float array
$article->embedding = $embedding;
$article->save();
```

VectorCast
----------

[](#vectorcast)

`VectorCast` handles conversion between MariaDB's binary VECTOR format and PHP float arrays.

```
protected function casts(): array
{
    return [
        'embedding' => \Devilsberg\LaravelMariadbVector\Casts\VectorCast::class,
    ];
}
```

- **Reading:** Decodes MariaDB's binary packed floats (32-bit IEEE 754) or JSON string format to `array`
- **Writing:** Converts `array` to a `VEC_FromText('[0.1, 0.2, ...]')` expression
- **Null-safe:** Returns `null` for null values in both directions
- **Empty-safe:** Returns `null` for empty arrays

The column supports `->nullable()` in migrations:

```
$table->vector('embedding', 768)->nullable();
```

Query Builder Macros
--------------------

[](#query-builder-macros)

All macros are registered on `Illuminate\Database\Eloquent\Builder`.

### whereVectorSimilarTo

[](#wherevectorsimilarto)

Filter results by vector distance threshold.

```
whereVectorSimilarTo(
    string $column,
    array $input,
    float $threshold,       // required — what counts as "similar" is application-specific
    ?string $metric = null  // defaults to config('vector.distance_metric')
)
```

```
Article::query()->whereVectorSimilarTo('embedding', $queryVector, 0.5)->get();

// Euclidean distance
Article::query()->whereVectorSimilarTo('embedding', $queryVector, 0.5, metric: 'EUCLIDEAN')->get();
```

Generates: `WHERE VEC_DISTANCE_COSINE(\`embedding`, VEC\_FromText(?)) &lt; ?`

### orderByVectorDistance

[](#orderbyvectordistance)

Sort results by vector distance (nearest first).

```
orderByVectorDistance(
    string $column,
    array $input,
    ?string $metric = null
)
```

```
Article::query()->orderByVectorDistance('embedding', $queryVector)->get();
```

Generates: `ORDER BY VEC_DISTANCE_COSINE(\`embedding`, VEC\_FromText(?)) asc`

### selectVectorDistance

[](#selectvectordistance)

Include the distance score in query results.

```
selectVectorDistance(
    string $column,
    array $input,
    string $as = 'distance',
    ?string $metric = null
)
```

```
Article::query()
    ->select('*')
    ->selectVectorDistance('embedding', $queryVector, as: 'score')
    ->orderByVectorDistance('embedding', $queryVector)
    ->get()
    ->each(fn ($article) => dump($article->title, $article->score));
```

Generates: `VEC_DISTANCE_COSINE(\`embedding`, VEC\_FromText(?)) as `score``

### nearestNeighbors

[](#nearestneighbors)

The recommended macro for most use cases. Computes the distance **once** per row as a normalized `score` column and orders results by highest score first. More efficient than chaining the three individual macros.

```
nearestNeighbors(
    string $column,
    array $input,
    Distance $distance = Distance::Cosine
)
```

```
use Devilsberg\LaravelMariadbVector\Distance;

Article::query()
    ->nearestNeighbors('embedding', $queryVector, Distance::Cosine)
    ->limit(10)
    ->get();

// With Euclidean distance
Article::query()
    ->nearestNeighbors('embedding', $queryVector, Distance::Euclidean)
    ->limit(5)
    ->get();
```

Generates:

```
SELECT *, 1.0 - (VEC_DISTANCE_COSINE(`embedding`, VEC_FromText(?))) as `score`
FROM `articles`
ORDER BY `score` desc
```

The `score` is a normalized similarity value — higher means more similar:

- **Cosine:** `1.0 - distance`, range approximately `[-1, 1]` (in practice `[0, 1]` for LLM embeddings)
- **Euclidean:** `1.0 - distance / SQRT(2)`, normalized to approximately `[0, 1]`

### Combining macros

[](#combining-macros)

For advanced queries where you need threshold filtering alongside ordering, use the individual macros:

```
$results = Article::query()
    ->select('id', 'title')
    ->whereVectorSimilarTo('embedding', $queryVector, 0.4)
    ->selectVectorDistance('embedding', $queryVector, as: 'score')
    ->orderByVectorDistance('embedding', $queryVector)
    ->limit(10)
    ->get();
```

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

[](#configuration)

Published to `config/vector.php`:

```
return [
    // Default vector dimensions (should match your embedding model output)
    'default_dimensions' => 768,

    // Distance metric: "COSINE" or "EUCLIDEAN"
    'distance_metric' => 'COSINE',
];
```

KeyDefaultDescription`default_dimensions``768`Default dimensions for vector columns`distance_metric``COSINE`Distance function: `COSINE` or `EUCLIDEAN`> **Note:** `DOT` product distance is not supported by MariaDB. Configuring it will throw an `InvalidArgumentException`.

Testing
-------

[](#testing)

Run the unit tests:

```
vendor/bin/phpunit --testsuite=Unit
```

Run the integration tests (requires a live MariaDB instance):

```
vendor/bin/phpunit --testsuite=Integration
```

Configure MariaDB credentials in `phpunit.xml`:

```

```

Run the full suite:

```
vendor/bin/phpunit
```

Support
-------

[](#support)

If this package saves you time, consider buying me a coffee.

[![ko-fi](https://camo.githubusercontent.com/201ef269611db7eb6b5d08e9f756ab8980df3014b64492770bdf13a6ed924641/68747470733a2f2f6b6f2d66692e636f6d2f696d672f676974687562627574746f6e5f736d2e737667)](https://ko-fi.com/devilsberg)

License
-------

[](#license)

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

###  Health Score

41

—

FairBetter than 87% of packages

Maintenance83

Actively maintained with recent releases

Popularity12

Limited adoption so far

Community6

Small or concentrated contributor base

Maturity53

Maturing project, gaining track record

 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.

###  Release Activity

Cadence

Every ~1 days

Total

3

Last Release

90d ago

### Community

Maintainers

![](https://www.gravatar.com/avatar/4ed1f0ffb6268c164461cd332b7950cf9129f0494bf19c7e44ca3e60151cc199?d=identicon)[erikros](/maintainers/erikros)

---

Top Contributors

[![erik-ros-devilsberg](https://avatars.githubusercontent.com/u/83531606?v=4)](https://github.com/erik-ros-devilsberg "erik-ros-devilsberg (3 commits)")

---

Tags

laraveldatabasemariadbeloquentvectorsimilarity-searchembeddingsvector-search

###  Code Quality

TestsPHPUnit

### Embed Badge

![Health badge](/badges/devilsberg-laravel-mariadb-vector/health.svg)

```
[![Health](https://phpackages.com/badges/devilsberg-laravel-mariadb-vector/health.svg)](https://phpackages.com/packages/devilsberg-laravel-mariadb-vector)
```

###  Alternatives

[anourvalar/eloquent-serialize

Laravel Query Builder (Eloquent) serialization

11222.5M32](/packages/anourvalar-eloquent-serialize)[mozex/laravel-scout-bulk-actions

Import, flush, and queue-import all your Laravel Scout searchable models at once. Auto-discovers models, runs in bulk, tracks progress.

1437.7k](/packages/mozex-laravel-scout-bulk-actions)[lacodix/laravel-model-filter

A Laravel package to filter, search and sort models with ease while fetching from database.

17555.1k](/packages/lacodix-laravel-model-filter)[waad/laravel-model-metadata

A robust Laravel package for handling metadata with JSON casting, custom relation names, and advanced querying capabilities.

854.1k](/packages/waad-laravel-model-metadata)[ramadan/easy-model

A Laravel package for enjoyably managing database queries.

111.6k](/packages/ramadan-easy-model)[helgesverre/chromadb

PHP Client for the Chromadb Rest API

321.1k](/packages/helgesverre-chromadb)

PHPackages © 2026

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