本文目录导读:

在PHP中连接和操作 Elasticsearch(ES),主要有以下几种方式:
使用官方客户端(推荐)
安装
composer require elasticsearch/elasticsearch
基本连接
<?php
require 'vendor/autoload.php';
use Elastic\Elasticsearch\ClientBuilder;
// 单节点连接
$client = ClientBuilder::create()
->setHosts(['localhost:9200'])
->build();
// 多节点连接(集群)
$client = ClientBuilder::create()
->setHosts([
'192.168.1.1:9200',
'192.168.1.2:9200',
'192.168.1.3:9200'
])
->build();
// 带认证的连接
$client = ClientBuilder::create()
->setHosts(['https://user:password@localhost:9200'])
->setSSLVerification(false) // 开发环境可以关闭SSL验证
->build();
基本操作示例
创建索引
$params = [
'index' => 'my_index',
'body' => [
'settings' => [
'number_of_shards' => 3,
'number_of_replicas' => 2
],
'mappings' => [
'properties' => [
'title' => [
'type' => 'text'
],
'content' => [
'type' => 'text'
],
'price' => [
'type' => 'float'
],
'created_at' => [
'type' => 'date',
'format' => 'yyyy-MM-dd HH:mm:ss'
]
]
]
]
];
$response = $client->indices()->create($params);
添加文档
// 单条添加
$params = [
'index' => 'my_index',
'id' => '1',
'body' => [
'title' => 'PHP教程',
'content' => '学习PHP编程',
'price' => 29.99,
'created_at' => '2024-01-15 10:30:00'
]
];
$response = $client->index($params);
// 批量添加
$params = ['body' => []];
for ($i = 1; $i <= 100; $i++) {
$params['body'][] = [
'index' => [
'_index' => 'my_index',
'_id' => $i
]
];
$params['body'][] = [
'title' => "文章{$i}",
'content' => "这是第{$i}篇文章的内容",
'price' => rand(10, 100),
'created_at' => date('Y-m-d H:i:s', strtotime("-{$i} days"))
];
}
$responses = $client->bulk($params);
搜索文档
// 基本搜索
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'match' => [
'title' => 'PHP'
]
],
'size' => 10,
'from' => 0,
'sort' => [
'price' => 'desc'
]
]
];
$response = $client->search($params);
// 处理结果
$hits = $response['hits']['hits'];
$total = $response['hits']['total']['value'];
foreach ($hits as $hit) {
echo "ID: " . $hit['_id'] . "\n";
echo "Score: " . $hit['_score'] . "\n";
print_r($hit['_source']);
echo "---\n";
}
// 高级搜索(多条件)
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'bool' => [
'must' => [
['match' => ['title' => 'PHP']],
['range' => ['price' => ['gte' => 20, 'lte' => 50]]]
],
'filter' => [
['term' => ['status' => 'active']]
]
]
],
'aggs' => [
'avg_price' => [
'avg' => ['field' => 'price']
],
'price_ranges' => [
'range' => [
'field' => 'price',
'ranges' => [
['to' => 30],
['from' => 30, 'to' => 60],
['from' => 60]
]
]
]
]
]
];
$response = $client->search($params);
更新文档
// 部分更新
$params = [
'index' => 'my_index',
'id' => '1',
'body' => [
'doc' => [
'price' => 39.99,
'updated_at' => date('Y-m-d H:i:s')
]
]
];
$response = $client->update($params);
// 通过脚本更新
$params = [
'index' => 'my_index',
'id' => '1',
'body' => [
'script' => [
'source' => 'ctx._source.price += params.discount',
'params' => ['discount' => -5]
]
]
];
$response = $client->updateByQuery($params);
删除文档
// 删除单个
$params = [
'index' => 'my_index',
'id' => '1'
];
$response = $client->delete($params);
// 条件删除
$params = [
'index' => 'my_index',
'body' => [
'query' => [
'range' => [
'created_at' => [
'lte' => '2024-01-01'
]
]
]
]
];
$response = $client->deleteByQuery($params);
使用CURL直接操作(无依赖)
function esRequest($method, $uri, $body = null) {
$url = "http://localhost:9200/{$uri}";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
curl_setopt($ch, CURLOPT_CUSTOMREQUEST, $method);
if ($body) {
curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($body));
curl_setopt($ch, CURLOPT_HTTPHEADER, ['Content-Type: application/json']);
}
$response = curl_exec($ch);
curl_close($ch);
return json_decode($response, true);
}
// 使用示例
$result = esRequest('GET', 'my_index/_search', [
'query' => [
'match' => ['title' => 'PHP']
]
]);
封装成服务类(推荐用于项目)
<?php
namespace App\Services;
use Elastic\Elasticsearch\ClientBuilder;
class ElasticsearchService
{
private $client;
private $index;
public function __construct($hosts = ['localhost:9200'], $index = 'default_index')
{
$this->client = ClientBuilder::create()
->setHosts($hosts)
->build();
$this->index = $index;
}
public function setIndex($index)
{
$this->index = $index;
return $this;
}
public function search($query, $page = 1, $size = 10, $sort = [])
{
$params = [
'index' => $this->index,
'body' => [
'query' => $query,
'from' => ($page - 1) * $size,
'size' => $size
]
];
if (!empty($sort)) {
$params['body']['sort'] = $sort;
}
try {
$response = $this->client->search($params);
return [
'total' => $response['hits']['total']['value'],
'hits' => $response['hits']['hits'],
'page' => $page,
'size' => $size
];
} catch (\Exception $e) {
return ['error' => $e->getMessage()];
}
}
public function indexDocument($id, $data)
{
$params = [
'index' => $this->index,
'id' => $id,
'body' => $data
];
return $this->client->index($params);
}
public function deleteDocument($id)
{
$params = [
'index' => $this->index,
'id' => $id
];
return $this->client->delete($params);
}
public function bulkIndex($documents)
{
$params = ['body' => []];
foreach ($documents as $doc) {
$params['body'][] = [
'index' => [
'_index' => $this->index,
'_id' => $doc['id']
]
];
$params['body'][] = $doc['data'];
}
return $this->client->bulk($params);
}
}
配置和最佳实践
连接池配置
$client = ClientBuilder::create()
->setHosts(['localhost:9200'])
->setConnectionPool('\Elasticsearch\ConnectionPool\StaticNoPingConnectionPool')
->setRetries(3)
->setHandler(ClientBuilder::singleHandler())
->build();
错误处理
try {
$response = $client->search($params);
} catch (\Elastic\Elasticsearch\Exception\ElasticsearchException $e) {
echo "ES错误: " . $e->getMessage();
} catch (\Exception $e) {
echo "一般错误: " . $e->getMessage();
}
性能优化
// 设置批量处理大小
$batchSize = 1000;
$documents = [/* ... */];
$params = ['body' => []];
foreach ($documents as $doc) {
$params['body'][] = [
'index' => ['_index' => 'my_index', '_id' => $doc['id']]
];
$params['body'][] = $doc['data'];
if (count($params['body']) >= $batchSize * 2) {
$client->bulk($params);
$params = ['body' => []];
}
}
// 处理剩余文档
if (!empty($params['body'])) {
$client->bulk($params);
}
调试和监控
// 开启调试模式
$logger = ClientBuilder::defaultLogger('path/to/logs/elastic.log');
$client = ClientBuilder::create()
->setHosts(['localhost:9200'])
->setLogger($logger)
->build();
// 查看请求信息
$response = $client->search($params);
echo "用时: " . $response['took'] . "ms\n";
echo "分片信息: " . print_r($response['_shards'], true);
选择哪种方式取决于你的项目需求:
- 小型项目:使用官方客户端最简单
- 大型项目:封装成服务类更易维护
- 无依赖需求:CURL方式最轻量
版权声明:NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
NBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
CBA直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
足球直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播
英超直播