nordsoftware/lumen-elasticsearch
Laravel Lumen integration for Elasticsearch. Provides service provider bindings and configuration to register an Elasticsearch client in your Lumen app, enabling easy indexing and searching with a familiar Laravel-style setup.
Installation:
composer require nordsoftware/lumen-elasticsearch
Add the service provider to bootstrap/app.php:
$app->register(Nordsoftware\LumenElasticsearch\ElasticsearchServiceProvider::class);
Configuration: Publish the config file:
php artisan vendor:publish --provider="Nordsoftware\LumenElasticsearch\ElasticsearchServiceProvider" --tag=config
Update config/elasticsearch.php with your Elasticsearch cluster details (e.g., host, port, scheme).
First Use Case: Inject the client into a Lumen controller or service:
use Nordsoftware\LumenElasticsearch\Facades\Elasticsearch;
public function search(Request $request)
{
$results = Elasticsearch::search('index_name', [
'query' => [
'match' => ['field_name' => $request->input('query')]
]
]);
return response()->json($results);
}
config/elasticsearch.php: Cluster configuration.app/Providers/ElasticsearchServiceProvider.php: Service binding logic.app/Exceptions/Handler.php: Custom exception handling for Elasticsearch errors.Search Operations:
// Basic search
$results = Elasticsearch::search('products', ['query' => ['match_all' => new \stdClass]]);
// Filtered search
$results = Elasticsearch::search('products', [
'query' => [
'bool' => [
'must' => [['match' => ['name' => 'laptop']]],
'filter' => [['range' => ['price' => ['gte' => 500]]]]
]
]
]);
Index Management:
// Create index
Elasticsearch::createIndex('new_index', [
'settings' => ['number_of_shards' => 1],
'mappings' => ['properties' => ['title' => ['type' => 'text']]]
]);
// Delete index
Elasticsearch::deleteIndex('old_index');
Document CRUD:
// Index a document
Elasticsearch::index('products', '1', ['name' => 'Laptop', 'price' => 999]);
// Get a document
$doc = Elasticsearch::get('products', '1');
// Update a document
Elasticsearch::update('products', '1', ['price' => 799]);
// Delete a document
Elasticsearch::delete('products', '1');
Bulk Operations:
$operations = [
['index' => ['_index' => 'products', '_id' => '1']],
['name' => 'Laptop'],
['index' => ['_index' => 'products', '_id' => '2']],
['name' => 'Phone']
];
Elasticsearch::bulk('products', $operations);
Middleware for Authentication: Use Lumen middleware to validate API keys or tokens before Elasticsearch operations:
$router->group(['middleware' => 'auth:api'], function () {
$router->post('/search', 'SearchController@search');
});
Caching Responses: Cache frequent search results using Lumen's cache:
$cacheKey = 'search_results_' . md5($request->input('query'));
$results = Cache::remember($cacheKey, 300, function () use ($request) {
return Elasticsearch::search('products', ['query' => ['match' => ['name' => $request->input('query')]]]);
});
Async Processing: Offload heavy indexing to queues (e.g., Laravel Horizon):
Queue::push(new IndexProductJob($product));
Connection Issues:
ConnectionRefusedError or timeouts.config/elasticsearch.php host/port/scheme. Use ping() to test connectivity:
if (!Elasticsearch::ping()) {
throw new \RuntimeException('Elasticsearch connection failed');
}
'hosts' => env('ELASTICSEARCH_HOSTS', 'localhost:9200'),
Index/Mapping Conflicts:
VersionConflictError or IllegalArgumentException when updating mappings.ignore_unmapped or recreate indices with updated mappings:
Elasticsearch::search('products', ['query' => ['match_all' => new \stdClass]], ['ignore_unmapped' => true]);
Rate Limiting:
TooManyRequestsError in production.use Nordsoftware\LumenElasticsearch\Exceptions\ElasticsearchException;
try {
$results = Elasticsearch::search('products', $query);
} catch (ElasticsearchException $e) {
if ($e->getStatusCode() === 429) {
sleep(2); // Retry after delay
return Elasticsearch::search('products', $query);
}
throw $e;
}
Deprecation Warnings:
create_function).elasticsearch/elasticsearch package:
composer update elasticsearch/elasticsearch
Enable Logging:
Add to config/elasticsearch.php:
'logger' => [
'enabled' => true,
'level' => 'debug',
'handler' => function () {
return new \Monolog\Handler\StreamHandler(storage_path('logs/elasticsearch.log'), \Monolog\Logger::DEBUG);
}
],
Use sniff() for Cluster Awareness:
Dynamically discover nodes in a cluster:
Elasticsearch::sniff();
Test Locally with Docker:
Use docker-compose.yml to spin up Elasticsearch:
version: '3'
services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.15.0
ports:
- "9200:9200"
environment:
- discovery.type=single-node
Custom Clients: Bind a custom Elasticsearch client in the service provider:
$app->bind('elasticsearch', function ($app) {
$client = Elasticsearch\ClientBuilder::create()
->setHosts(['custom_host:9200'])
->setLogger($app['logger'])
->build();
return new Nordsoftware\LumenElasticsearch\Elasticsearch($client);
});
Query Builders: Create reusable query builders for common searches:
class ProductSearchBuilder
{
public static function build($query)
{
return [
'query' => [
'bool' => [
'must' => [['query_string' => ['query' => $query]]],
'filter' => [
['term' => ['category' => 'electronics']],
['range' => ['price' => ['lte' => 1000]]]
]
]
]
];
}
}
Event Listeners: Trigger events for index/document operations (e.g., sync with a database):
Elasticsearch::listen('indexed', function ($index, $type, $id, $data) {
// Sync to database or trigger other services
});
How can I help you explore Laravel packages today?