Skip to content

Commit 0d2c4b6

Browse files
committed
Document adapter package API
1 parent 4de10e9 commit 0d2c4b6

20 files changed

Lines changed: 711 additions & 84 deletions

README.md

Lines changed: 131 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# OpenSearch Adapter
22

3-
A PHP adapter for the official [OpenSearch PHP client](https://github.com/opensearch-project/opensearch-php).
3+
A PHP adapter for the [OpenSearch PHP client](https://github.com/opensearch-project/opensearch-php).
44

55
## Installation
66

@@ -10,9 +10,9 @@ Install the package with Composer:
1010
composer require directorytree/opensearch-adapter
1111
```
1212

13-
## Usage
13+
## Creating Managers
1414

15-
Create the adapter managers with an `OpenSearch\Client` instance:
15+
Create the adapter managers from an `OpenSearch\Client` instance:
1616

1717
```php
1818
use DirectoryTree\OpenSearchAdapter\Documents\DocumentManager;
@@ -23,4 +23,131 @@ $documents = new DocumentManager($client);
2323
$indices = new IndexManager($client);
2424
```
2525

26-
The adapter provides value objects for documents, index mappings, settings, aliases, search requests, and search responses.
26+
## Managing Indices
27+
28+
Use an index blueprint when you want fluent mapping and settings builders:
29+
30+
```php
31+
use DirectoryTree\OpenSearchAdapter\Indices\IndexBlueprint;
32+
use DirectoryTree\OpenSearchAdapter\Indices\Mapping;
33+
use DirectoryTree\OpenSearchAdapter\Indices\Settings;
34+
35+
$mapping = (new Mapping)
36+
->keyword('id')
37+
->text('title')
38+
->object('author', [
39+
'properties' => [
40+
'name' => ['type' => 'text'],
41+
],
42+
]);
43+
44+
$settings = (new Settings)->index([
45+
'number_of_shards' => 1,
46+
'number_of_replicas' => 0,
47+
]);
48+
49+
$indices->create(new IndexBlueprint('books', $mapping, $settings));
50+
```
51+
52+
Raw OpenSearch arrays are supported when you already have a mapping or settings payload:
53+
54+
```php
55+
$indices->createRaw(
56+
'books',
57+
mapping: [
58+
'properties' => [
59+
'title' => ['type' => 'text'],
60+
],
61+
],
62+
settings: [
63+
'index' => [
64+
'number_of_shards' => 1,
65+
],
66+
],
67+
);
68+
```
69+
70+
## Indexing Documents
71+
72+
Documents contain the OpenSearch document ID and source payload:
73+
74+
```php
75+
use DirectoryTree\OpenSearchAdapter\Documents\Document;
76+
77+
$documents->index('books', collect([
78+
new Document('1', [
79+
'title' => 'The Hobbit',
80+
]),
81+
]));
82+
```
83+
84+
Routing values can be attached by document ID:
85+
86+
```php
87+
use DirectoryTree\OpenSearchAdapter\Documents\Routing;
88+
89+
$routing = (new Routing)->add('1', 'tenant-1');
90+
91+
$documents->index('books', collect([
92+
new Document('1', [
93+
'title' => 'The Hobbit',
94+
]),
95+
]), routing: $routing);
96+
```
97+
98+
## Searching Documents
99+
100+
Build a search request with raw OpenSearch query fragments:
101+
102+
```php
103+
use DirectoryTree\OpenSearchAdapter\Search\SearchRequest;
104+
105+
$request = (new SearchRequest([
106+
'match' => [
107+
'title' => 'hobbit',
108+
],
109+
]))
110+
->size(10)
111+
->highlight([
112+
'fields' => [
113+
'title' => new stdClass,
114+
],
115+
]);
116+
117+
$response = $documents->search('books', $request);
118+
119+
$total = $response->total();
120+
121+
$hits = $response->hits()->map(function ($hit) {
122+
return $hit->document()->content();
123+
});
124+
```
125+
126+
## Aliases
127+
128+
Aliases can include optional filters and routing values:
129+
130+
```php
131+
use DirectoryTree\OpenSearchAdapter\Indices\Alias;
132+
133+
$indices->putAlias('books', new Alias(
134+
'tenant-books',
135+
filter: [
136+
'term' => [
137+
'tenant_id' => 1,
138+
],
139+
],
140+
routing: 'tenant-1',
141+
));
142+
143+
$aliases = $indices->getAliases('books');
144+
```
145+
146+
## Raw Responses
147+
148+
Search response objects expose the original OpenSearch payload through `raw()`:
149+
150+
```php
151+
$rawHit = $response->hits()->first()->raw();
152+
$rawResponse = $response->raw();
153+
```

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "directorytree/opensearch-adapter",
3-
"description": "A PHP adapter for the official OpenSearch PHP client",
3+
"description": "A PHP adapter for the OpenSearch PHP client",
44
"keywords": [
55
"opensearch",
66
"adapter",

src/Documents/Document.php

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,26 +7,50 @@
77

88
class Document implements Arrayable
99
{
10+
/**
11+
* The OpenSearch document identifier.
12+
*/
1013
protected string $id;
1114

15+
/**
16+
* The document source payload.
17+
*
18+
* @var array<string, mixed>
19+
*/
1220
protected array $content;
1321

22+
/**
23+
* Create a new document instance.
24+
*
25+
* @param array<string, mixed> $content
26+
*/
1427
public function __construct(string $id, array $content)
1528
{
1629
$this->id = $id;
1730
$this->content = $content;
1831
}
1932

33+
/**
34+
* Get the document identifier.
35+
*/
2036
public function id(): string
2137
{
2238
return $this->id;
2339
}
2440

41+
/**
42+
* Get the full document source or a single value from it.
43+
*/
2544
public function content(?string $key = null): mixed
2645
{
2746
return Arr::get($this->content, $key);
2847
}
2948

49+
/**
50+
* Get the array representation of the document.
51+
*
52+
* @return array{id: string, content: array<string, mixed>}
53+
*/
3054
public function toArray(): array
3155
{
3256
return [

src/Documents/DocumentManager.php

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,15 +10,25 @@
1010

1111
class DocumentManager
1212
{
13+
/**
14+
* The OpenSearch client instance.
15+
*/
1316
protected Client $client;
1417

18+
/**
19+
* Create a new document manager instance.
20+
*/
1521
public function __construct(Client $client)
1622
{
1723
$this->client = $client;
1824
}
1925

2026
/**
21-
* @param Collection|Document[] $documents
27+
* Index the given documents into OpenSearch.
28+
*
29+
* @param Collection<int, Document> $documents
30+
*
31+
* @throws BulkRequestException
2232
*/
2333
public function index(
2434
string $indexName,
@@ -53,7 +63,11 @@ public function index(
5363
}
5464

5565
/**
56-
* @param string[] $documentIds
66+
* Delete the given documents from OpenSearch.
67+
*
68+
* @param array<int, string> $documentIds
69+
*
70+
* @throws BulkRequestException
5771
*/
5872
public function delete(
5973
string $indexName,
@@ -86,6 +100,11 @@ public function delete(
86100
return $this;
87101
}
88102

103+
/**
104+
* Delete documents that match the given OpenSearch query.
105+
*
106+
* @param array<string, mixed> $query
107+
*/
89108
public function deleteByQuery(string $indexName, array $query, bool $refresh = false): self
90109
{
91110
$params = [
@@ -99,6 +118,9 @@ public function deleteByQuery(string $indexName, array $query, bool $refresh = f
99118
return $this;
100119
}
101120

121+
/**
122+
* Search an index using the given search request.
123+
*/
102124
public function search(string $indexName, SearchRequest $request): SearchResponse
103125
{
104126
$params = array_merge($request->toArray(), ['index' => $indexName]);

src/Documents/Routing.php

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,20 +4,34 @@
44

55
class Routing
66
{
7+
/**
8+
* The routing values keyed by document ID.
9+
*
10+
* @var array<string, string>
11+
*/
712
protected array $routing = [];
813

14+
/**
15+
* Add a routing value for the given document ID.
16+
*/
917
public function add(string $documentId, string $value): self
1018
{
1119
$this->routing[$documentId] = $value;
1220

1321
return $this;
1422
}
1523

24+
/**
25+
* Determine if routing exists for the given document ID.
26+
*/
1627
public function has(string $documentId): bool
1728
{
1829
return isset($this->routing[$documentId]);
1930
}
2031

32+
/**
33+
* Get the routing value for the given document ID.
34+
*/
2135
public function get(string $documentId): ?string
2236
{
2337
return $this->routing[$documentId] ?? null;

src/Exceptions/BulkRequestException.php

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,27 +6,50 @@
66

77
class BulkRequestException extends ErrorException
88
{
9+
/**
10+
* The OpenSearch bulk response.
11+
*
12+
* @var array<string, mixed>
13+
*/
914
protected array $response;
1015

16+
/**
17+
* Create a new bulk request exception instance.
18+
*
19+
* @param array<string, mixed> $response
20+
*/
1121
public function __construct(array $response)
1222
{
1323
$this->response = $response;
1424

1525
parent::__construct($this->makeErrorFromResponse());
1626
}
1727

28+
/**
29+
* Get the exception context.
30+
*
31+
* @return array{response: array<string, mixed>}
32+
*/
1833
public function context(): array
1934
{
2035
return [
2136
'response' => $this->getResponse(),
2237
];
2338
}
2439

40+
/**
41+
* Get the OpenSearch bulk response.
42+
*
43+
* @return array<string, mixed>
44+
*/
2545
public function getResponse(): array
2646
{
2747
return $this->response;
2848
}
2949

50+
/**
51+
* Create the exception message from the OpenSearch bulk response.
52+
*/
3053
protected function makeErrorFromResponse(): string
3154
{
3255
$items = $this->response['items'] ?? [];

0 commit comments

Comments
 (0)