Link Search Menu Expand Document Documentation Menu

PHP client

The OpenSearch PHP client provides a safer and easier way to interact with your OpenSearch cluster. Rather than using OpenSearch from a browser and potentially exposing your data to the public, you can build an OpenSearch client that takes care of sending requests to your cluster. The client contains a library of APIs that let you perform different operations on your cluster and return a standard response body.

This getting started guide illustrates how to connect to OpenSearch, index documents, and run queries. For the client source code, see the opensearch-php repo.

Setup

To add the client to your project, install it using composer:

composer require opensearch-project/opensearch-php

To install a specific major version of the client, run the following command:

composer require opensearch-project/opensearch-php:<version>

Then require the autload file from composer in your code:

require __DIR__ . '/vendor/autoload.php';

Connecting to OpenSearch

Use a PSR client to connect to OpenSearch. For information about the supported PSR clients, see Client factories. For information about basic authentication using PSR clients, see Basic authentication using a PSR client.

Connecting to Amazon OpenSearch Service

For information about connecting to Amazon OpenSearch Service, see IAM authentication using a PSR client.

Creating an index

To create an OpenSearch index with custom settings, use the following code:

public function createIndex()
{
    $this->client->indices()->create([
        'index' => INDEX_NAME,
        'body' => [
            'settings' => [
                'index' => [
                    'number_of_shards' => 4
                ]
            ]
        ]
    ]);
}

Indexing a document

You can index a document into OpenSearch using the following code:

public function create()
{
    $time = time();
    $this->existingID = $time;
    $this->deleteID = $time . '_uniq';


    // Create a document passing the id
    $this->client->create([
        'id' => $time,
        'index' => INDEX_NAME,
        'body' => $this->getData($time)
    ]);

    // Create a document passing the id
    $this->client->create([
        'id' => $this->deleteID,
        'index' => INDEX_NAME,
        'body' => $this->getData($time)
    ]);

    // Create a document without passing the id (will be generated automatically)
    $this->client->create([
        'index' => INDEX_NAME,
        'body' => $this->getData($time + 1)
    ]);
}

Searching for documents

The following code uses a multi_match query to search for “miller” in the title and director fields. It boosts the documents where “miller” appears in the title field:

public function search()
{
    $docs = $this->client->search([
        //index to search in or '_all' for all indices
        'index' => INDEX_NAME,
        'size' => 1000,
        'body' => [
            'query' => [
                'prefix' => [
                    'name' => 'wrecking'
                ]
            ]
        ]
    ]);
    var_dump($docs['hits']['total']['value'] > 0);

    // Search for it
    $docs = $this->client->search([
        'index' => INDEX_NAME,
        'body' => [
            'size' => 5,
            'query' => [
                'multi_match' => [
                    'query' => 'miller',
                    'fields' => ['title^2', 'director']
                ]
            ]
        ]
    ]);
    var_dump($docs['hits']['total']['value'] > 0);
}

Deleting a document

You can delete a document using the following code:

public function deleteByID()
{
    $this->client->delete([
        'id' => $this->deleteID,
        'index' => INDEX_NAME,
    ]);
}

Deleting an index

You can delete an index using the following code:

public function deleteByIndex()
{
    $this->client->indices()->delete([
        'index' => INDEX_NAME
    ]);
}

Sample program

The following sample program creates a client and performs various OpenSearch operations:

<?php
require __DIR__ . '/vendor/autoload.php';

define('INDEX_NAME', 'test_elastic_index_name2');

class MyOpenSearchClass
{

    protected ?\OpenSearch\Client $client;
    protected $existingID = 1668504743;
    protected $deleteID = 1668504743;
    protected $bulkIds = [];


    public function __construct()
    {
        // Simple Setup
        $this->client = (new \OpenSearch\GuzzleClientFactory())->create([
            'base_uri' => 'https://localhost:9200',
            'auth' => ['admin', getenv('OPENSEARCH_PASSWORD')],
            'verify' => false, // Disables SSL verification for local development.
        ]);
    }


    // Create an index with non-default settings.
    public function createIndex()
    {
        $this->client->indices()->create([
            'index' => INDEX_NAME,
            'body' => [
                'settings' => [
                    'index' => [
                        'number_of_shards' => 4
                    ]
                ]
            ]
        ]);
    }

    public function info()
    {
        // Print OpenSearch version information on console.
        var_dump($this->client->info());
    }

    // Create a document
    public function create()
    {
        $time = time();
        $this->existingID = $time;
        $this->deleteID = $time . '_uniq';


        // Create a document passing the id
        $this->client->create([
            'id' => $time,
            'index' => INDEX_NAME,
            'body' => $this->getData($time)
        ]);

        // Create a document passing the id
        $this->client->create([
            'id' => $this->deleteID,
            'index' => INDEX_NAME,
            'body' => $this->getData($time)
        ]);

        // Create a document without passing the id (will be generated automatically)
        $this->client->create([
            'index' => INDEX_NAME,
            'body' => $this->getData($time + 1)
        ]);

        //This should throw an exception because ID already exists
        // $this->client->create([
        //     'id' => $this->existingID,
        //     'index' => INDEX_NAME,
        //     'body' => $this->getData($this->existingID)
        // ]);
    }

    public function update()
    {
        $this->client->update([
            'id' => $this->existingID,
            'index' => INDEX_NAME,
            'body' => [
                //data must be wrapped in 'doc' object
                'doc' => ['name' => 'updated']
            ]
        ]);
    }

    public function bulk()
    {
        $bulkData = [];
        $time = time();
        for ($i = 0; $i < 20; $i++) {
            $id = ($time + $i) . rand(10, 200);
            $bulkData[] = [
                'index' => [
                    '_index' => INDEX_NAME,
                    '_id' => $id,
                ]
            ];
            $this->bulkIds[] = $id;
            $bulkData[] = $this->getData($time + $i);
        }
        //will not throw exception! check $response for error
        $response = $this->client->bulk([
            //default index
            'index' => INDEX_NAME,
            'body' => $bulkData
        ]);

        //give elastic a little time to create before update
        sleep(2);

        // bulk update
        for ($i = 0; $i < 15; $i++) {
            $bulkData[] = [
                'update' => [
                    '_index' => INDEX_NAME,
                    '_id' => $this->bulkIds[$i],
                ]
            ];
            $bulkData[] = [
                'doc' => [
                    'name' => 'bulk updated'
                ]
            ];
        }

        //will not throw exception! check $response for error
        $response = $this->client->bulk([
            //default index
            'index' => INDEX_NAME,
            'body' => $bulkData
        ]);
    }
    public function deleteByQuery(string $query)
    {
        if ($query == '') {
            return;
        }
        $this->client->deleteByQuery([
            'index' => INDEX_NAME,
            'q' => $query
        ]);
    }

    // Delete a single document
    public function deleteByID()
    {
        $this->client->delete([
            'id' => $this->deleteID,
            'index' => INDEX_NAME,
        ]);
    }

    public function search()
    {
        $docs = $this->client->search([
            //index to search in or '_all' for all indices
            'index' => INDEX_NAME,
            'size' => 1000,
            'body' => [
                'query' => [
                    'prefix' => [
                        'name' => 'wrecking'
                    ]
                ]
            ]
        ]);
        var_dump($docs['hits']['total']['value'] > 0);

        // Search for it
        $docs = $this->client->search([
            'index' => INDEX_NAME,
            'body' => [
                'size' => 5,
                'query' => [
                    'multi_match' => [
                        'query' => 'miller',
                        'fields' => ['title^2', 'director']
                    ]
                ]
            ]
        ]);
        var_dump($docs['hits']['total']['value'] > 0);
    }

    // Write queries in SQL
    public function searchUsingSQL()
    {
        $docs = $this->client->sql()->query([
          'query' => "SELECT * FROM " . INDEX_NAME . " WHERE name = 'wrecking'",
          'format' => 'json'
        ]);
        var_dump($docs['hits']['total']['value'] > 0);
    }

    public function getMultipleDocsByIDs()
    {
        $docs = $this->client->search([
            //index to search in or '_all' for all indices
            'index' => INDEX_NAME,
            'body' => [
                'query' => [
                    'ids' => [
                        'values' => $this->bulkIds
                    ]
                ]
            ]
        ]);
        var_dump($docs['hits']['total']['value'] > 0);
    }

    public function getOneByID()
    {
        $docs = $this->client->search([
            //index to search in or '_all' for all indices
            'index' => INDEX_NAME,
            'size' => 1,
            'body' => [
                'query' => [
                    'bool' => [
                        'filter' => [
                            'term' => [
                                '_id' => $this->existingID
                            ]
                        ]
                    ]
                ]
            ]
        ]);
        var_dump($docs['hits']['total']['value'] > 0);
    }

    public function searchByPointInTime()
    {
        $result = $this->client->createPointInTime([
            'index' => INDEX_NAME,
            'keep_alive' => '10m'
        ]);
        $pitId = $result['pit_id'];

        // Get first page of results in Point-in-Time
        $result = $this->client->search([
            'body' => [
                'pit' => [
                    'id' => $pitId,
                    'keep_alive' => '10m',
                ],
                'size' => 10, // normally you would do 10000
                'query' => [
                    'match_all' => (object)[]
                ],
                'sort' => '_id',
            ]
        ]);
        var_dump($result['hits']['total']['value'] > 0);

        $last = end($result['hits']['hits']);
        $lastSort = $last['sort'] ?? null;

        // Get next page of results in Point-in-Time
        $result = $this->client->search([
            'body' => [
                'pit' => [
                    'id' => $pitId,
                    'keep_alive' => '10m',
                ],
                'search_after' => $lastSort,
                'size' => 10, // normally you would do 10000
                'query' => [
                    'match_all' => (object)[]
                ],
                'sort' => '_id',
            ]
        ]);
        var_dump($result['hits']['total']['value'] > 0);

        // Close Point-in-Time
        $result = $this->client->deletePointInTime([
            'body' => [
              'pit_id' => $pitId,
            ]
        ]);
        var_dump($result['pits'][0]['successful']);
    }

    // Delete index
    public function deleteByIndex()
    {
        $this->client->indices()->delete([
            'index' => INDEX_NAME
        ]);
    }

    //simple data to index
    public function getData($time = -1)
    {
        if ($time == -1) {
            $time = time();
        }
        return [
            'name' => date('c', $time) . " - i came in like a wrecking ball",
            'time' => $time,
            'date' => date('c', $time)
        ];
    }
}

try {

    $e = new MyOpenSearchClass();
    $e->info();
    $e->createIndex();
    $e->create();
    //give elastic a little time to create before update
    sleep(2);
    $e->update();
    $e->bulk();
    $e->getOneByID();
    $e->getMultipleDocsByIDs();
    $e->search();
    $e->searchUsingSQL();
    $e->searchByPointInTime();
    $e->deleteByQuery('');
    $e->deleteByID();
    $e->deleteByIndex();
} catch (\Throwable $th) {
    echo 'uncaught error ' . $th->getMessage() . "\n";
}

Next steps