pdphilip/elasticlens
ElasticLens brings Elasticsearch power to Laravel models with Eloquent-style queries. Define your own index models, mappings, and schema—no black box. Run phrase/term searches, filters, embedded fields, geo distance sorting, and pagination with fluent, readable APIs.
Start by installing the package via Composer and publishing its config:
composer require pdphilip/elasticlens
php artisan lens:install
php artisan migrate
Then configure config/database.php with an elasticsearch connection (per the README). Next, enable indexing on your model using the Indexable trait and create a corresponding Indexed{Model} class (e.g., IndexedUser). That’s enough for basic syncing and searching via:
User::viaIndex()->searchTerm('coffee')->get(); // now returns `User[]` directly
First read the Indexing your Base-Model docs section and run php artisan lens:make ModelName to scaffold the Indexed* model.
use Indexable; to your Eloquent model and create App\Models\Indexes\Indexed{Model}. Automatic sync happens on create/update/delete.User::viaIndex()
->where('status', 'active')
->searchPhrase('java developer')
->orderByDesc('created_at')
->get(); // returns `User[]` directly (no `->getBase()` needed)
posts, settings) in the field map to denormalize nested data — crucial for avoiding joins at search time.mapIndexBuild() to define schema requirements and enforce index versions via lens:migrate/lens:rebuild.lens:health, lens:status, lens:rebuild-index User to inspect and maintain indexes in CI/CD or ops workflows.searchTerm, filterGeoPoint, whereNestedObject) alongside standard Laravel query builders — ideal for advanced filtering (e.g., geo + status + time window).excludeIndex() in your Indexed{Model} to prevent specific records from being indexed (e.g., ->where('is_draft', true)).use HasIndexableSoftDeletes; on the index model (or configure globally in config/elasticlens.php).viaIndex()->get() now returns base models (e.g., User[]) by default. Use ->getIndex() or ->paginateIndex() if you explicitly need IndexedUser[] instances.getBase() is Deprecated for Default Usage: While still functional, ->getBase() is no longer necessary. Remove it unless you intentionally need index model access.get() returns base models, intermediate objects (e.g., builders, scopes) still reference index models. Be cautious with type-hinting and serialization.FieldMap::make() in your Indexed* model’s buildIndex() method to explicitly define field types and analyzers.user_logs) won’t work unless declared in the fieldMap as nested types.Indexable watches the base model. If using custom observers or scaling across many models, register specific classes in config/elasticlens.php’s observed_models.lens:migrate to diff and migrate indexes incrementally — avoid lens:rebuild-index in production unless necessary.withHighlights() to get matches, but remember to include the field in fieldMap and request _source for full content.How can I help you explore Laravel packages today?