PHP 环境要求:PHP >= 7.2 + 安装 ES 客户端
composer require elasticsearch/elasticsearch
php
<?php
require 'vendor/autoload.php'; // 加载 composer 依赖
use Elasticsearch\ClientBuilder;
use DateTime;
// ========== 连接 Elasticsearch ==========
// 1. 基本连接(对应 Python 基础连接)
$client = ClientBuilder::create()
->setHosts(['http://localhost:9200']) // ES 地址
->build();
// 2. 带认证连接(账号密码 + 证书)
$client = ClientBuilder::create()
->setHosts(['https://localhost:9200'])
->setBasicAuthentication('elastic', 'password') // 认证
->setCABundle('/path/to/http_ca.crt') // 证书
->build();
// 3. 多节点连接
$client = ClientBuilder::create()
->setHosts([
'http://node1:9200',
'http://node2:9200',
'http://node3:9200',
])
->build();
// 验证连接(输出 ES 信息)
print_r($client->info());
// ========== 索引操作 ==========
// 创建索引(结构与 Python 完全一致)
$indexParams = [
'index' => 'articles', // 索引名
'body' => [
'settings' => [
'number_of_shards' => 1, // 主分片
'number_of_replicas' => 0, // 副本
],
'mappings' => [
'properties' => [
'title' => ['type' => 'text', 'analyzer' => 'standard'],
'content' => ['type' => 'text'],
'author' => ['type' => 'keyword'],
'publish_date' => ['type' => 'date'],
'views' => ['type' => 'integer'],
'tags' => ['type' => 'keyword'],
]
]
]
];
// 创建索引,忽略已存在错误(400)
try {
$client->indices()->create($indexParams);
} catch (Exception $e) {}
// 检查索引是否存在
if ($client->indices()->exists(['index' => 'articles'])) {
echo "索引存在\n";
}
// 删除索引(忽略 400/404 错误)
try {
$client->indices()->delete(['index' => 'articles']);
} catch (Exception $e) {}
// ========== 文档操作 ==========
// 插入单个文档(ID=1)
$doc = [
'title' => 'Elasticsearch入门教程',
'content' => 'Elasticsearch是一个分布式搜索引擎...',
'author' => '张三',
'publish_date' => (new DateTime())->format('Y-m-d H:i:s'),
'views' => 1000,
'tags' => ['elasticsearch', '搜索', '教程']
];
$response = $client->index([
'index' => 'articles',
'id' => 1,
'body' => $doc
]);
echo "插入结果:" . $response['result'] . "\n";
// ========== 批量插入文档(2~101) ==========
$params = ['body' => []];
for ($i = 2; $i < 102; $i++) {
// 批量第一行:指定操作
$params['body'][] = [
'index' => [
'_index' => 'articles',
'_id' => $i
]
];
// 批量第二行:文档内容
$params['body'][] = [
'title' => "文章标题$i",
'content' => "文章内容$i",
'author' => "作者" . $i % 5,
'publish_date' => (new DateTime())->format('Y-m-d H:i:s'),
'views' => $i * 100
];
}
// 执行批量
$responses = $client->bulk($params);
$success = $i - 2 - count($responses['items']);
echo "成功:" . ($i - 2) . ",失败:" . count($responses['items']) . "\n";
// ========== 获取单个文档 ==========
$doc = $client->get([
'index' => 'articles',
'id' => 1
]);
print_r($doc['_source']);
// ========== 更新文档 ==========
$client->update([
'index' => 'articles',
'id' => 1,
'body' => [
'doc' => [
'views' => 1500,
'updated_at' => (new DateTime())->format('Y-m-d H:i:s')
]
]
]);
// ========== 删除文档 ==========
$client->delete([
'index' => 'articles',
'id' => 1
]);
// ========== 搜索操作 ==========
// match 查询(标题搜索)
$result = $client->search([
'index' => 'articles',
'body' => [
'query' => [
'match' => [
'title' => 'Elasticsearch 教程'
]
]
]
]);
// 遍历搜索结果
foreach ($result['hits']['hits'] as $hit) {
echo "ID: {$hit['_id']}, Score: {$hit['_score']}\n";
echo "Title: {$hit['_source']['title']}\n";
}
// ========== bool 复合查询 ==========
$result = $client->search([
'index' => 'articles',
'body' => [
'query' => [
'bool' => [
'must' => [
['match' => ['content' => '搜索引擎']]
],
'filter' => [
['range' => ['views' => ['gte' => 500]]],
['term' => ['author' => '张三']]
]
]
],
'sort' => [
['views' => 'desc'],
'_score'
],
'from' => 0,
'size' => 10,
'_source' => ['title', 'author', 'views']
]
]);
echo "总命中:" . $result['hits']['total']['value'] . "\n";
foreach ($result['hits']['hits'] as $hit) {
print_r($hit['_source']);
}
// ========== 高亮搜索 ==========
$result = $client->search([
'index' => 'articles',
'body' => [
'query' => [
'match' => [
'content' => 'Elasticsearch'
]
],
'highlight' => [
'fields' => [
'content' => [
'pre_tags' => ['<em>'],
'post_tags' => ['</em>']
]
]
]
]
]);
foreach ($result['hits']['hits'] as $hit) {
if (isset($hit['highlight'])) {
echo implode(',', $hit['highlight']['content']) . "\n";
}
}
// ========== 聚合分析:按作者分组 + 平均浏览量 ==========
$result = $client->search([
'index' => 'articles',
'body' => [
'size' => 0,
'aggs' => [
'by_author' => [
'terms' => [
'field' => 'author',
'size' => 10
],
'aggs' => [
'avg_views' => [
'avg' => ['field' => 'views']
]
]
]
]
]
]);
// 输出聚合结果
foreach ($result['aggregations']['by_author']['buckets'] as $bucket) {
$author = $bucket['key'];
$count = $bucket['doc_count'];
$avg = round($bucket['avg_views']['value']);
echo "作者:$author,文章数:$count,平均浏览:$avg\n";
}
// ========== 封装类(与 Python 完全对应) ==========
class ElasticsearchClient
{
private $es;
// 构造函数:创建连接
public function __construct($hosts = ['http://localhost:9200'])
{
$this->es = ClientBuilder::create()->setHosts($hosts)->build();
}
// 创建索引
public function createIndex($indexName, $mappings = null, $settings = null)
{
$body = [];
if ($settings) $body['settings'] = $settings;
if ($mappings) $body['mappings'] = $mappings;
if (!$this->es->indices()->exists(['index' => $indexName])) {
$this->es->indices()->create([
'index' => $indexName,
'body' => $body
]);
return true;
}
return false;
}
// 插入文档
public function indexDocument($indexName, $doc, $docId = null)
{
$params = [
'index' => $indexName,
'body' => $doc
];
if ($docId) $params['id'] = $docId;
return $this->es->index($params);
}
// 搜索文档
public function search($indexName, $query, $size = 10, $from = 0, $sort = null)
{
$body = [
'query' => $query,
'size' => $size,
'from' => $from
];
if ($sort) $body['sort'] = $sort;
$result = $this->es->search([
'index' => $indexName,
'body' => $body
]);
return [
'total' => $result['hits']['total']['value'],
'hits' => array_map(function ($hit) {
return $hit['_source'];
}, $result['hits']['hits'])
];
}
// 按查询条件删除
public function deleteByQuery($indexName, $query)
{
return $this->es->deleteByQuery([
'index' => $indexName,
'body' => ['query' => $query]
]);
}
// 关闭客户端
public function close()
{
$this->es = null;
}
}
// ========== 封装类使用示例 ==========
$client = new ElasticsearchClient();
// 创建测试索引
$client->createIndex('test_index', [
'properties' => [
'title' => ['type' => 'text'],
'content' => ['type' => 'text']
]
]);
// 插入文档
$client->indexDocument('test_index', [
'title' => '测试文档',
'content' => '这是一个测试'
]);
// 搜索
$res = $client->search('test_index', [
'match' => ['title' => '测试']
]);
print_r($res);