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

    }


}
相关推荐
wearegogog1234 小时前
Centos7下docker的jenkins下载并配置jdk与maven
java·docker·jenkins
Yyyy4824 小时前
Ansible Role修改IP地址与主机名
linux·服务器·php
Elasticsearch4 小时前
Simple MCP Client - 连接到 Elasticsearch MCP 并进行自然语言搜索
elasticsearch
JaguarJack4 小时前
多进程环境中解决 PHP 文件系统锁定问题指南
后端·php
罗技1239 小时前
Elasticsearch、OpenSearch 与 Easysearch:三代搜索引擎的演化与抉择
大数据·elasticsearch·搜索引擎
极限实验室18 小时前
Elasticsearch 备份:snapshot 镜像使用篇
数据库·elasticsearch
stwood00720 小时前
codeigniter换服务器之后,会员登录之后又跳回登录页面的解决方法
服务器·php
vxtkjzxt8881 天前
自动化脚本矩阵运营
开发语言·php
gb42152871 天前
elasticsearch索引多长时间刷新一次(智能刷新索引根据数据条数去更新)
大数据·elasticsearch·jenkins