PHP操作elasticsearch7.8

ElasticSearch

安装驱动

复制代码
composer require elasticsearch/elasticsearch'

操作

php 复制代码
<?php

namespace Tests\Unit;

use Elasticsearch\ClientBuilder;
use Elasticsearch\Common\Exceptions\Curl\CouldNotConnectToHost;
use Elasticsearch\Common\Exceptions\ElasticsearchException;
use Elasticsearch\Common\Exceptions\Missing404Exception;
use Exception;
use PHPUnit\Framework\TestCase;

class ExampleTest extends TestCase
{
    //创建索引
    public function testExample()
    {
        // 创建客户端时确保使用同步模式
        $client = ClientBuilder::create()
            ->setHosts(['http://localhost:9200'])
            ->setRetries(2)
            ->build();

        $indexName = 'your_index';

        try {
            // 尝试创建索引(如果不存在)
            try {
                $client->indices()->create([
                    'index' => $indexName,
                    'body' => [
                        'settings' => [
                            'number_of_shards' => 1,
                            'number_of_replicas' => 0
                        ]
                    ]
                ]);
                echo "索引 '$indexName' 创建成功\n";
            } catch (ElasticsearchException $e) {
                // 如果索引已存在,Elasticsearch会抛出异常,这里忽略这个异常
                if (strpos($e->getMessage(), 'resource_already_exists_exception') === false) {
                    // 不是索引已存在的异常,需要重新抛出
                    throw $e;
                }
                echo "索引 '$indexName' 已存在\n";
            }

            // 执行搜索操作
            try {
                $response = $client->search([
                    'index' => $indexName,
                    'body' => [
                        'query' => ['match_all' => new \stdClass()]
                    ]
                ]);

                // 处理成功响应
                echo "搜索成功,找到 " . $response['hits']['total']['value'] . " 条结果\n";
            } catch (Missing404Exception $e) {
                // 处理404错误(资源不存在)
                echo "404错误:" . $e->getMessage() . "\n";
            }

        } catch (CouldNotConnectToHost $e) {
            // 处理连接失败(ES服务未启动或地址错误)
            echo "连接失败:请检查ES服务是否启动,地址是否正确\n";
            echo "错误详情:" . $e->getMessage() . "\n";
        } catch (ElasticsearchException $e) {
            // 处理其他ES相关错误
            echo "ES错误:" . $e->getMessage() . "\n";
        } catch (Exception $e) {
            // 处理自定义异常或其他错误
            echo "错误:" . $e->getMessage() . "\n";
        }
    }
    //获取索引列表
    public function testExample2(){
        // 创建客户端时确保使用同步模式
        $client = ClientBuilder::create()
            ->setHosts(['http://localhost:9200'])
            ->setRetries(2)
            ->build();
        //删除索引
//        $client->indices()->delete(['index' => 'your_index']);
       $result =  $client->cat()->indices([
            'format' => 'json'
        ]);
        echo "索引列表:\n";
        foreach ($result as $index) {
            echo "索引名:{$index['index']},状态:{$index['health']},文档数:{$index['docs.count']}\n";
        }


    }

    public function testDocMethod(){
        // 创建客户端时确保使用同步模式
        $client = ClientBuilder::create()
            ->setHosts(['http://localhost:9200'])
            ->setRetries(2)
            ->build();
        // 2. 定义要插入的文档数据
        $document = [
            'name' => '张三',
            'age' => 30,
            'email' => 'zhangsan@example.com',
            'hobbies' => ['篮球', '阅读'],
            'created_at' => date('Y-m-d H:i:s')
        ];

// 3. 配置插入参数
        $params = [
            'index' => 'users', // 目标索引名(若不存在,默认会自动创建)
             'id' => 'user_1001', // 可选:手动指定文档ID,不指定则ES自动生成
            'body' => $document  // 文档内容
        ];
        $response = $client->index($params);
        if ($response['result'] === 'created') {
            echo "文档插入成功!\n";
            echo "文档ID:{$response['_id']}\n";
            echo "索引:{$response['_index']}\n";
            echo "版本号:{$response['_version']}\n"; // 新文档版本为1
        } elseif ($response['result'] === 'updated') {
            // 若指定了已存在的ID,则会更新文档,result为'updated'
            echo "文档更新成功!\n";
        }
    }


    public function testDocSearch(){
        // 创建客户端时确保使用同步模式
        $client = ClientBuilder::create()
            ->setHosts(['http://localhost:9200'])
            ->build();
//            ->setRetries(2);
        // 基础查询:匹配所有文档
        $params = [
            'index' => "users",
            'body' => [
                'query' => [
                    'match_all' => new \stdClass() // match_all 查询匹配所有文档
                ],
                'size' => 10, // 最多返回10条结果(默认10)
                'from' => 0   // 从第0条开始(用于分页)
            ]
        ];
        // 简单查询:匹配 name 字段包含"张三"的文档
//        $params = [
//            'index' => $index,
//            'body' => [
//                'query' => [
//                    'match' => [
//                        'name' => '张三' // 匹配 name 字段包含"张三"的文档
//                        // 多字段匹配:'multi_match' => ['query' => '关键词', 'fields' => ['name', 'email']]
//                    ]
//                ]
//            ]
//        ];
//        精确匹配(term/terms)
//term:精确匹配单个值(适合数字、日期、keyword 类型字段)。
//terms:匹配多个值中的任意一个。
//
//        // 精确匹配 age=30
//        $params = [
//            'body' => [
//                'query' => [
//                    'term' => ['age' => 30]
//                ]
//            ]
//        ];
//
//// 匹配 age 为 25、30、35 中的任意一个
//        $params = [
//            'body' => [
//                'query' => [
//                    'terms' => ['age' => [25, 30, 35]]
//                ]
//            ]
//        ];
//        范围查询(range)
//匹配字段值在指定范围内的文档(适合数字、日期):
//        $params = [
//            'body' => [
//                'query' => [
//                    'range' => [
//                        'age' => [
//                            'gte' => 20, // >=20
//                            'lte' => 40, // <=40
//                            // 其他符号:gt(>), lt(<)
//                        ]
//                    ]
//                ]
//            ]
//        ];
//        组合条件查询(bool)
//通过 must(必须满足)、should(满足其一)、must_not(必须不满足)组合多条件:
//        $params = [
//            'body' => [
//                'query' => [
//                    'bool' => [
//                        'must' => [
//                            ['match' => ['hobbies' => '篮球']] // 必须喜欢篮球
//                        ],
//                        'filter' => [
//                            ['range' => ['age' => ['gt' => 25]]] // 年龄>25(不影响评分)
//                        ],
//                        'must_not' => [
//                            ['term' => ['status' => '禁用']] // 排除禁用用户
//                        ],
//                        'should' => [
//                            ['match' => ['city' => '北京']],
//                            ['match' => ['city' => '上海']] // 至少满足一个城市
//                        ]
//                    ]
//                ]
//            ]
//        ];

//        排序与分页
//        $params = [
//            'body' => [
//                'query' => [/* ... */],
//                'sort' => [
//                    ['age' => ['order' => 'desc']], // 按 age 降序
//                    ['created_at' => ['order' => 'asc']] // 再按创建时间升序
//                ],
//                'from' => 10, // 从第10条开始(跳过前10条)
//                'size' => 10 // 返回10条
//            ]
//        ];


        //模糊查询
//        $params = [
//            'index' => $indexName,
//            'body' => [
//                'query' => [
//                    'fuzzy' => [
//                        'name' => [ // 要查询的字段(通常是 text 或 keyword 类型)
//                            'value' => $keyword, // 关键词
//                            'fuzziness' => 'AUTO', // 允许的模糊程度(默认 AUTO)
//                            'prefix_length' => 1, // 前缀不允许模糊的字符数(前1个字符必须准确)
//                            'max_expansions' => 10 // 最多匹配的候选词数量(避免性能问题)
//                        ]
//                    ]
//                ]
//            ]
//        ];


        //高亮查询
//        $params = [
//            'index' => $indexName,
//            'body' => [
//                'query' => [
//                    'match' => [
//                        'content' => $keyword // 在 content 字段中匹配关键词
//                    ]
//                ],
//                'highlight' => [
//                    'fields' => [
//                        'content' => new \stdClass() // 对 content 字段启用高亮(使用默认配置)
//                    ],
//                    'pre_tags' => ['<em class="highlight">'], // 高亮前缀标签
//                    'post_tags' => ['</em>'] // 高亮后缀标签
//                ]
//            ]
//        ];


        //最大值查询
//        $params = [
//            'index' => $indexName,
//            'body' => [
//                'size' => 0, // 不需要返回原始文档,只关心聚合结果
//                'aggs' => [ // 定义聚合
//                    'max_' . $field => [ // 聚合名称(自定义,用于后续解析结果)
//                        'max' => [
//                            'field' => $field // 要计算最大值的字段
//                        ]
//                    ]
//                ]
//            ]
//        ];


        //分组查询






        //-------------------------响应结果--------------------
        // 响应示例
//        [
//            'hits' => [
//                'total' => ['value' => 100], // 总匹配数
//                'hits' => [
//                    [
//                        '_id' => '123', // 文档ID
//                        '_source' => [...], // 文档原始数据
//                        '_score' => 1.2 // 匹配得分(相关性)
//                    ],
//                    // ...更多文档
//                ]
//            ]
//        ]



        $response = $client->search($params);
//        $client->delete([//删除操作
//            'index' => $indexName,
//            'id'    => $documentId
//        ]);

        // 解析结果
        echo "匹配到 " . $response['hits']['total']['value'] . " 条数据:\n";
        foreach ($response['hits']['hits'] as $hit) {
            echo "ID: {$hit['_id']},数据:" . json_encode($hit['_source']) . "\n";
        }



    }


    public function testUpdateBulk(){
        // 连接 Elasticsearch
        $client = ClientBuilder::create()
            ->setHosts(['http://localhost:9200']) // 替换为你的 ES 地址
            ->build();

        $indexName = 'users'; // 索引名

// 批量更新的文档信息(每个元素对应一个文档的更新操作)
        $documents = [
            [
                'id' => '1', // 文档 ID
                'update_data' => ['age' => 31, 'updated_at' => date('Y-m-d H:i:s')] // 要更新的字段
            ],
            [
                'id' => '2',
                'update_data' => ['age' => 28, 'hobbies' => ['足球', '音乐']]
            ]
        ];

        try {
            $params = ['body' => []];

            // 组装批量更新参数
            foreach ($documents as $doc) {
                // 每个更新操作需要先添加一个 "update" 指令
                $params['body'][] = [
                    'update' => [
                        '_index' => $indexName,
                        '_id' => $doc['id']
                    ]
                ];

                // 接着添加更新的内容(支持 partial update,只更新指定字段)
                $params['body'][] = [
                    'doc' => $doc['update_data'] // doc 表示要更新的字段
                    // 可选:如果文档不存在,是否创建(默认 false)
                    // 'doc_as_upsert' => true
                ];
            }

            // 执行批量更新
            $response = $client->bulk($params);

            // 解析结果
            if (empty($response['errors'])) {
                echo "批量更新成功!\n";
                foreach ($response['items'] as $item) {
                    $id = $item['update']['_id'];
                    $status = $item['update']['status'];
                    echo "文档 ID: {$id},状态: {$status}\n";
                }
            } else {
                echo "部分更新失败:\n";
                foreach ($response['items'] as $item) {
                    if (isset($item['update']['error'])) {
                        $id = $item['update']['_id'];
                        $error = $item['update']['error']['reason'];
                        echo "文档 ID: {$id},错误: {$error}\n";
                    }
                }
            }

        } catch (Exception $e) {
            echo "批量更新失败:" . $e->getMessage() . "\n";
        }

    }

    public function testCreateBulk(){
        // 连接 Elasticsearch
        $client = ClientBuilder::create()
            ->setHosts(['http://localhost:9200']) // 替换为你的 ES 地址
            ->build();

        $indexName = 'users'; // 目标索引名

// 要批量插入的文档数据(数组形式,每个元素是一条文档)
        $documents = [
            [
                'id' => '1001', // 可选:手动指定文档ID,不指定则ES自动生成
                'data' => [
                    'name' => '张三',
                    'age' => 28,
                    'email' => 'zhangsan@example.com',
                    'created_at' => date('Y-m-d H:i:s')
                ]
            ],
            [
                'id' => '1002',
                'data' => [
                    'name' => '李四',
                    'age' => 32,
                    'email' => 'lisi@example.com',
                    'created_at' => date('Y-m-d H:i:s')
                ]
            ],
            [
                // 不指定ID,由ES自动生成
                'data' => [
                    'name' => '王五',
                    'age' => 25,
                    'email' => 'wangwu@example.com',
                    'created_at' => date('Y-m-d H:i:s')
                ]
            ]
        ];

        try {
            $params = ['body' => []];

            // 组装批量插入参数
            foreach ($documents as $doc) {
                // 每个插入操作需要先添加一个 "index" 指令
                $action = [
                    'index' => [
                        '_index' => $indexName
                    ]
                ];
                // 如果指定了ID,添加到指令中
                if (isset($doc['id'])) {
                    $action['index']['_id'] = $doc['id'];
                }

                // 将指令和文档数据添加到批量请求中
                $params['body'][] = $action;
                $params['body'][] = $doc['data'];
            }

            // 执行批量插入
            $response = $client->bulk($params);

            // 解析结果
            if (empty($response['errors'])) {
                echo "批量插入成功!共插入 " . count($documents) . " 条文档\n";
                foreach ($response['items'] as $item) {
                    $id = $item['index']['_id'];
                    $status = $item['index']['status']; // 201 表示创建成功
                    echo "文档 ID: {$id},状态: {$status}\n";
                }
            } else {
                echo "部分插入失败:\n";
                foreach ($response['items'] as $item) {
                    if (isset($item['index']['error'])) {
                        $id = $item['index']['_id'] ?? '未知';
                        $error = $item['index']['error']['reason'];
                        echo "文档 ID: {$id},错误: {$error}\n";
                    }
                }
            }

        } catch (Exception $e) {
            echo "批量插入失败:" . $e->getMessage() . "\n";
        }

    }


}
相关推荐
ServBay8 小时前
垃圾堆里编码?真的不要怪 PHP 不行
后端·php
洛森唛10 小时前
ElasticSearch查询语句Query String详解:从入门到精通
后端·elasticsearch
用户9623779544811 小时前
CTF 伪协议
php
洛森唛1 天前
Elasticsearch DSL 查询语法大全:从入门到精通
后端·elasticsearch
BingoGo3 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php
JaguarJack3 天前
当你的 PHP 应用的 API 没有限流时会发生什么?
后端·php·服务端
Elasticsearch4 天前
如何使用 Agent Builder 排查 Kubernetes Pod 重启和 OOMKilled 事件
elasticsearch
BingoGo4 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php
JaguarJack4 天前
OpenSwoole 26.2.0 发布:支持 PHP 8.5、io_uring 后端及协程调试改进
后端·php·服务端
Elasticsearch5 天前
通用表达式语言 ( CEL ): CEL 输入如何改进 Elastic Agent 集成中的数据收集
elasticsearch