PHP项目中如何使用Elasticsearch?

wen PHP项目 1

本文目录导读:

PHP项目中如何使用Elasticsearch?

  1. 安装Elasticsearch PHP客户端
  2. 基本连接配置
  3. 常用操作示例
  4. 高级特性
  5. 最佳实践
  6. 实战项目结构建议
  7. 注意事项
  8. 常用命令工具

在PHP项目中使用Elasticsearch,通常有以下几个步骤和注意事项:

安装Elasticsearch PHP客户端

推荐使用官方客户端库:

composer require elasticsearch/elasticsearch

基本连接配置

<?php
require 'vendor/autoload.php';
use Elastic\Elasticsearch\ClientBuilder;
// 创建客户端
$client = ClientBuilder::create()
    ->setHosts(['localhost:9200'])  // 单节点
    // 多节点
    // ->setHosts(['localhost:9200', 'localhost:9201'])
    ->build();

带认证的连接

$client = ClientBuilder::create()
    ->setHosts(['https://localhost:9200'])
    ->setBasicAuthentication('username', 'password')  // 基础认证
    ->setSSLVerification(false)  // 跳过SSL验证(开发环境)
    ->build();

常用操作示例

索引管理

// 创建索引
$params = [
    'index' => 'articles',
    'body' => [
        'settings' => [
            'number_of_shards' => 3,
            'number_of_replicas' => 2
        ],
        'mappings' => [
            'properties' => [
                'title' => ['type' => 'text'],
                'content' => ['type' => 'text'],
                'author' => ['type' => 'keyword'],
                'publish_date' => ['type' => 'date'],
                'tags' => ['type' => 'keyword']
            ]
        ]
    ]
];
$response = $client->indices()->create($params);
// 检查索引是否存在
$exists = $client->indices()->exists(['index' => 'articles']);
// 删除索引
$client->indices()->delete(['index' => 'articles']);

文档增删改

// 添加/更新文档
$params = [
    'index' => 'articles',
    'id' => '1',  // 可选,不指定则自动生成
    'body' => [
        'title' => 'Elasticsearch入门教程',
        'content' => '本文介绍Elasticsearch的基本概念和使用方法...',
        'author' => '张三',
        'publish_date' => '2024-01-15',
        'tags' => ['elasticsearch', '搜索引擎']
    ]
];
$response = $client->index($params);
// 批量导入
$params = ['body' => []];
for ($i = 1; $i <= 100; $i++) {
    $params['body'][] = [
        'index' => [
            '_index' => 'articles',
            '_id' => $i
        ]
    ];
    $params['body'][] = [
        'title' => "文章标题{$i}",
        'content' => "文章内容{$i}..."
    ];
}
$responses = $client->bulk($params);
// 删除文档
$client->delete([
    'index' => 'articles',
    'id' => '1'
]);

搜索查询

// 基础搜索
$params = [
    'index' => 'articles',
    'body' => [
        'query' => [
            'match' => [
                'title' => 'Elasticsearch'
            ]
        ],
        'size' => 10,  // 返回数量
        'from' => 0    // 偏移量(分页)
    ]
];
$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";
    echo "Title: " . $hit['_source']['title'] . "\n\n";
}
// 复杂查询
$params = [
    'index' => 'articles',
    'body' => [
        'query' => [
            'bool' => [
                'must' => [
                    ['match' => ['title' => 'PHP']],
                    ['match' => ['content' => 'Elasticsearch']]
                ],
                'filter' => [
                    ['term' => ['author' => '张三']],
                    ['range' => ['publish_date' => ['gte' => '2024-01-01']]]
                ]
            ]
        ],
        'sort' => [
            'publish_date' => ['order' => 'desc']
        ],
        'aggs' => [
            'by_author' => [
                'terms' => ['field' => 'author']
            ]
        ]
    ]
];
$response = $client->search($params);

高级特性

聚合查询

$params = [
    'index' => 'orders',
    'body' => [
        'size' => 0,
        'aggs' => [
            'total_sales' => [
                'sum' => ['field' => 'amount']
            ],
            'sales_by_category' => [
                'terms' => ['field' => 'category'],
                'aggs' => [
                    'avg_price' => ['avg' => ['field' => 'amount']]
                ]
            ]
        ]
    ]
];

高亮显示

$params = [
    'index' => 'articles',
    'body' => [
        'query' => [
            'match' => ['content' => 'Elasticsearch']
        ],
        'highlight' => [
            'fields' => [
                'content' => [
                    'pre_tags' => ['<strong>'],
                    'post_tags' => ['</strong>']
                ]
            ]
        ]
    ]
];

最佳实践

连接池管理

// 使用连接池提高性能
$client = ClientBuilder::create()
    ->setHosts(['localhost:9200'])
    ->setConnectionPool('\Elasticsearch\ConnectionPool\StaticNoPingConnectionPool')
    ->setRetries(2)
    ->build();

日志记录

$logger = ClientBuilder::defaultLogger('path/to/logs/elasticsearch.log');
$client = ClientBuilder::create()
    ->setHosts(['localhost:9200'])
    ->setLogger($logger)
    ->build();

错误处理

use Elastic\Elasticsearch\Exception\ClientResponseException;
use Elastic\Elasticsearch\Exception\MissingParameterException;
use Elastic\Elasticsearch\Exception\ServerResponseException;
try {
    $response = $client->search($params);
} catch (ClientResponseException $e) {
    // 4xx错误
    echo "请求错误: " . $e->getMessage();
} catch (ServerResponseException $e) {
    // 5xx错误
    echo "服务器错误: " . $e->getMessage();
} catch (MissingParameterException $e) {
    echo "缺少参数: " . $e->getMessage();
}

实战项目结构建议

// ElasticsearchService.php
class ElasticsearchService
{
    private $client;
    public function __construct()
    {
        $this->client = ClientBuilder::create()
            ->setHosts([env('ELASTICSEARCH_HOST')])
            ->setBasicAuthentication(
                env('ELASTICSEARCH_USER'),
                env('ELASTICSEARCH_PASS')
            )
            ->build();
    }
    // 文章搜索
    public function searchArticles($keyword, $page = 1, $perPage = 10)
    {
        $params = [
            'index' => 'articles',
            'body' => [
                'query' => [
                    'multi_match' => [
                        'query' => $keyword,
                        'fields' => ['title^3', 'content^2', 'tags']
                    ]
                ],
                'from' => ($page - 1) * $perPage,
                'size' => $perPage,
                'highlight' => [
                    'fields' => [
                        'title' => new \stdClass(),
                        'content' => new \stdClass()
                    ]
                ]
            ]
        ];
        return $this->client->search($params);
    }
    // 同步数据
    public function syncArticle($article)
    {
        $params = [
            'index' => 'articles',
            'id' => $article['id'],
            'body' => [
                'title' => $article['title'],
                'content' => strip_tags($article['content']),
                'author' => $article['author'],
                'publish_date' => $article['created_at'],
                'tags' => $article['tags']
            ]
        ];
        return $this->client->index($params);
    }
}

注意事项

  1. 数据同步:需要建立可靠的同步机制(实时或定时)将MySQL/MongoDB数据同步到ES
  2. 索引策略:合理设计mapping,避免使用dynamic mapping
  3. 分词器:中文建议使用ik分词器
  4. 性能优化:批量操作时使用bulk API,避免频繁单条操作
  5. 安全:线上环境务必开启认证和SSL

常用命令工具

# 查看索引
curl -X GET 'localhost:9200/_cat/indices?v'
# 查看索引映射
curl -X GET 'localhost:9200/articles/_mapping'
# 查看索引设置
curl -X GET 'localhost:9200/articles/_settings'

这个流程基本涵盖了PHP项目中集成Elasticsearch的主要场景,根据实际需求可以进一步扩展和优化。

抱歉,评论功能暂时关闭!