Link Search Menu Expand Document Documentation Menu

PHP 客户端

OpenSearch PHP 客户端提供了一种更安全、更简便的方式来与您的 OpenSearch 集群交互。您无需通过浏览器使用 OpenSearch 并可能将数据暴露给公众,而是可以构建一个 OpenSearch 客户端来处理向集群发送请求。该客户端包含一个 API 库,可让您在集群上执行各种操作并返回标准响应体。

本入门指南介绍了如何连接到 OpenSearch、索引文档和运行查询。有关客户端源代码,请参阅 opensearch-php 仓库

设置

要将客户端添加到您的项目,请使用 composer 进行安装

composer require opensearch-project/opensearch-php

要安装特定主版本的客户端,请运行以下命令

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

然后在您的代码中从 composer 导入自动加载文件

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

连接到 OpenSearch

使用 PSR 客户端连接到 OpenSearch。有关受支持的 PSR 客户端的信息,请参阅客户端工厂。有关使用 PSR 客户端进行基本身份验证的信息,请参阅使用 PSR 客户端进行基本身份验证

连接到 Amazon OpenSearch 服务

有关连接到 Amazon OpenSearch Service 的信息,请参阅使用 PSR 客户端进行 IAM 身份验证

创建索引

要创建具有自定义设置的 OpenSearch 索引,请使用以下代码

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

索引文档

您可以使用以下代码将文档索引到 OpenSearch 中

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)
    ]);
}

搜索文档

以下代码使用 multi_match 查询在标题和导演字段中搜索“miller”。它提高了“miller”出现在标题字段中的文档的权重。

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);
}

删除文档

您可以使用以下代码删除文档

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

删除索引

您可以使用以下代码删除索引

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

示例程序

以下示例程序创建了一个客户端并执行各种 OpenSearch 操作

<?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://: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";
}

后续步骤

剩余 350 字符

有问题?

想要贡献?