A PHP adapter for the OpenSearch PHP client.
Install the package with Composer:
composer require directorytree/opensearch-adapterCreate the adapter managers from an OpenSearch\Client instance:
useDirectoryTree\OpenSearchAdapter\Documents\DocumentManager;
useDirectoryTree\OpenSearchAdapter\Indices\IndexManager;
useOpenSearch\Client;
$documents = newDocumentManager($client);
$indices = newIndexManager($client);Use an index blueprint when you want fluent mapping and settings builders:
useDirectoryTree\OpenSearchAdapter\Indices\IndexBlueprint;
useDirectoryTree\OpenSearchAdapter\Indices\Mapping;
useDirectoryTree\OpenSearchAdapter\Indices\Settings;
$mapping = (newMapping)
->dynamic('strict')
->keyword('id')
->text('title')
->object('author', [
'properties' => [
'name' => ['type' => 'text'],
],
]);
$settings = (newSettings)->index([
'number_of_shards' => 1,
'number_of_replicas' => 0,
'refresh_interval' => '1s',
]);
$indices->create(newIndexBlueprint('books', $mapping, $settings));Use field() for less common, custom, or newer OpenSearch field types:
$mapping = (newMapping)->field('embedding', 'custom_vector', [
'dimension' => 1536,
]);Settings include top-level setters for common OpenSearch settings groups:
$settings = (newSettings)
->index([
'number_of_shards' => 1,
'number_of_replicas' => 0,
])
->analysis([
'analyzer' => [
'content' => [
'type' => 'custom',
'tokenizer' => 'whitespace',
],
],
])
->similarity([
'default' => [
'type' => 'BM25',
],
]);Use set() for top-level settings groups that do not have a dedicated method:
$settings = (newSettings)
->set('custom_group', [
'enabled' => true,
]);Documents contain the OpenSearch document ID and source payload:
useDirectoryTree\OpenSearchAdapter\Documents\Document;
$documents->index('books', [
newDocument('1', [
'title' => 'The Hobbit',
]),
]);Document routing values can be attached by document ID:
useDirectoryTree\OpenSearchAdapter\Documents\DocumentRouting;
$routing = DocumentRouting::make('1', 'tenant-1');
$documents->index('books', [
newDocument('1', [
'title' => 'The Hobbit',
]),
], routing: $routing);Build a search request with raw OpenSearch query fragments:
useDirectoryTree\OpenSearchAdapter\Search\SearchRequest;
$request = (newSearchRequest([
'match' => [
'title' => 'hobbit',
],
]))
->size(10)
->highlight([
'fields' => [
'title' => newstdClass,
],
]);
$response = $documents->search('books', $request);
$total = $response->total();
$hits = array_map(
fn ($hit) => $hit->document()->source(),
$response->hits(),
);Aliases can include optional filters and routing values:
useDirectoryTree\OpenSearchAdapter\Indices\Alias;
$indices->putAlias('books', newAlias(
'tenant-books',
filter: [
'term' => [
'tenant_id' => 1,
],
],
routing: 'tenant-1',
));
$aliases = $indices->getAliases('books');Apply multiple alias changes atomically when switching between versioned indexes:
useDirectoryTree\OpenSearchAdapter\Indices\Alias;
useDirectoryTree\OpenSearchAdapter\Indices\AliasActions;
$actions = (newAliasActions)
->remove('books_blue', 'books')
->add('books_green', newAlias('books', isWriteIndex: true));
$indices->updateAliases($actions);An old physical index can be removed in the same atomic operation:
$actions = (newAliasActions)
->remove('books_blue', 'books')
->add('books_green', newAlias('books', isWriteIndex: true))
->removeIndex('books_retired');Search response objects expose the original OpenSearch payload through raw():
$rawHit = $response->hits()[0]->raw();
$rawResponse = $response->raw();This package builds on a lot of the foundation and prior work from Ivan Babenko and his Elasticsearch Laravel ecosystem packages.
We're grateful for the work he has shared with the Laravel community. If this package helps your work, consider supporting Ivan through GitHub Sponsors.