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

    }


}
相关推荐
明明跟你说过4 小时前
Kafka 与 Elasticsearch 的集成应用案例深度解析
大数据·elk·elasticsearch·kafka·big data·bigdata
拾-光4 小时前
【Git】命令大全:从入门到高手,100 个最常用命令速查(2026 版)
java·大数据·人工智能·git·python·elasticsearch·设计模式
醉颜凉4 小时前
Elasticsearch 实战:数据自动化清理完全指南(ILM + 定时删除 + 最佳实践)
elasticsearch·自动化·jenkins
2301_816997884 小时前
性能调优(基于 Elasticsearch 8.x)
大数据·elasticsearch·搜索引擎
不会摸鱼的小鱼7 小时前
WSL 安装 Ubuntu 22.04 到指定磁盘
数据库·postgresql·php
淼淼爱喝水11 小时前
DVWA和Pikachu命令注入漏洞检测实验
安全·web安全·php·pikachu·dvwa
专注VB编程开发20年11 小时前
json和python元组,列表,字典对比
开发语言·python·json·php
怀旧,12 小时前
【Linux网络编程】15. Reactor 反应堆模式
linux·网络·php
Elasticsearch12 小时前
通过项目标签和路由,在 Elasticsearch Serverless 中实现更快的跨项目搜索
elasticsearch
Dylan的码园13 小时前
2026年免费远程控制软件哪个好?ToDesk向日葵UU远程免费版横评,不限次数不限时长
服务器·开发语言·php