PHP操作elasticsearch7.8
ElasticSearch
安装驱动
composer require elasticsearch/elasticsearch'
操作
<?phpnamespace 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";}}}