cmsig/seal-meilisearch-adapter
composer require cmsig/seal cmsig/seal-meilisearch-adapter
use Meilisearch\Client;
use CmsIg\Seal\Adapter\Meilisearch\MeilisearchAdapter;
use CmsIg\Seal\Engine;
$client = new Client('http://127.0.0.1:7700'); // Replace with your Meilisearch endpoint
$engine = new Engine(
new MeilisearchAdapter($client),
$schema // Your SEAL schema definition
);
$document = new \CmsIg\Seal\Document\Document('product', [
'id' => '123',
'name' => 'Laptop',
'price' => 999.99,
]);
$engine->index($document);
Add to .env:
MEILISEARCH_DSN=meilisearch://apiKey@127.0.0.1:7700?tls=true
Retrieve in Laravel config:
$dsn = config('services.meilisearch.dsn');
$client = new Client($dsn);
Define a schema for your documents (e.g., ProductSchema):
use CmsIg\Seal\Schema\Field\Text;
use CmsIg\Seal\Schema\Field\Number;
use CmsIg\Seal\Schema\Schema;
$schema = new Schema('product', [
'name' => new Text(),
'price' => new Number(),
]);
Batch Indexing:
$documents = [
new \CmsIg\Seal\Document\Document('product', ['id' => '1', 'name' => 'Phone']),
new \CmsIg\Seal\Document\Document('product', ['id' => '2', 'name' => 'Tablet']),
];
$engine->indexMany($documents);
Upsert (Update or Insert):
$engine->upsert($document);
$results = $engine->search('Laptop', [
'limit' => 10,
'attributesToRetrieve' => ['name', 'price'],
]);
// services.php
'meilisearch' => function () {
$client = new Client(config('services.meilisearch.dsn'));
return new Engine(new MeilisearchAdapter($client), $this->app->make(ProductSchema::class));
},
// ProductObserver.php
public function saved(Product $product)
{
$document = new \CmsIg\Seal\Document\Document('product', [
'id' => $product->id,
'name' => $product->name,
'price' => $product->price,
]);
app('meilisearch')->upsert($document);
}
http://127.0.0.1:7700/docs/health).try {
$engine->index($document);
} catch (\Meilisearch\Exceptions\MeilisearchException $e) {
Log::error('Meilisearch error: ' . $e->getMessage());
}
DSN Format:
meilisearch:// for basic connections.apiKey@ for authentication.?tls=true for secure connections.meilisearch://admin:masterKey@localhost:7700?tls=true.Schema Mismatches:
Validate schema fields against Meilisearch’s supported types (e.g., avoid unsupported types like GeoPoint unless wrapped in a custom field).
indexMany() for bulk inserts/updates to reduce network overhead.id field (Meilisearch uses this for updates/deletes).Custom Fields:
Extend CmsIg\Seal\Schema\Field\Field for Meilisearch-specific types (e.g., RankingField):
class RankingField extends Field
{
public function getMeilisearchType(): string
{
return 'ranking';
}
}
Query Modifiers:
Leverage Meilisearch’s advanced query syntax via SEAL’s search() method:
$results = $engine->search('Laptop', [
'filter' => ['price < 1000'],
'sort' => ['price:asc'],
]);
Connection Timeouts: Ensure Meilisearch is reachable and the DSN is correct. Test with:
$client->health(); // Throws exception if unreachable
Rate Limiting: Meilisearch may throttle requests. Implement exponential backoff in retries:
use Symfony\Component\Process\Exception\ProcessFailedException;
try {
$engine->index($document);
} catch (ProcessFailedException $e) {
sleep(2 ** $attempt); // Exponential backoff
$attempt++;
retry();
}
Schema Evolution: Meilisearch does not support schema changes post-index creation. Rebuild indices for schema updates:
meilisearch index create product --primary-key id
How can I help you explore Laravel packages today?