laravel-mariadb-vector maintained by devilsberg
Laravel MariaDB Vector
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
- PHP 8.4+
- Laravel 12+
- MariaDB 11.7+
Installation
composer require devilsberg/laravel-mariadb-vector
Publish the config file:
php artisan vendor:publish --tag=mariadb-vector-config
Quick Start
1. Create a migration
Schema::create('articles', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->vector('embedding', 768);
$table->timestamps();
});
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
$embedding = $yourEmbeddingProvider->embed($article->body); // your code
$article->embedding = $embedding; // float array, e.g. [0.1, 0.2, ...]
$article->save();
4. Search by similarity
$queryVector = $yourEmbeddingProvider->embed('climate change effects');
$results = Article::query()
->whereVectorSimilarTo('embedding', $queryVector, 0.5)
->orderByVectorDistance('embedding', $queryVector)
->selectVectorDistance('embedding', $queryVector, as: 'score')
->get();
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 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<float> - Writing: Converts
array<float>to aVEC_FromText('[0.1, 0.2, ...]')expression - Null-safe: Returns
nullfor null values in both directions - Empty-safe: Returns
nullfor empty arrays
The column supports ->nullable() in migrations:
$table->vector('embedding', 768)->nullable();
Query Builder Macros
All macros are registered on Illuminate\Database\Eloquent\Builder.
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(?)) < ?`
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
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``
Combining macros
$results = Article::query()
->select('id', 'title')
->whereVectorSimilarTo('embedding', $queryVector, 0.4)
->selectVectorDistance('embedding', $queryVector, as: 'score')
->orderByVectorDistance('embedding', $queryVector)
->limit(10)
->get();
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',
];
| Key | Default | Description |
|---|---|---|
default_dimensions |
768 |
Default dimensions for vector columns |
distance_metric |
COSINE |
Distance function: COSINE or EUCLIDEAN |
Note:
DOTproduct distance is not supported by MariaDB. Configuring it will throw anInvalidArgumentException.
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:
<php>
<env name="DB_HOST" value="127.0.0.1"/>
<env name="DB_PORT" value="3306"/>
<env name="DB_DATABASE" value="your_test_db"/>
<env name="DB_USERNAME" value="your_user"/>
<env name="DB_PASSWORD" value="your_password"/>
</php>
Run the full suite:
vendor/bin/phpunit
Support
If this package saves you time, consider buying me a coffee.
License
The MIT License (MIT). Please see License File for more information.