ThinkPHP6.2+Elasticsearch实战:构建千万级商品搜索系统
一、全文搜索技术选型对比
方案 |
MySQL LIKE |
Elasticsearch |
TP内置搜索 |
搜索速度 |
慢(全表扫描) |
极快(倒排索引) |
中等 |
分词能力 |
无 |
支持多语言分词 |
基础分词 |
并发性能 |
100-1000 QPS |
10000+ QPS |
3000 QPS |
数据规模 |
百万级 |
亿级 |
千万级 |
二、核心实现方案
1. Elasticsearch服务集成
// config/elasticsearch.php
return [
'hosts' => [
env('ES_HOST', '127.0.0.1:9200')
],
'retries' => 3,
'connection_pool' => 'ElasticsearchConnectionPoolSimpleConnectionPool',
'selector' => 'ElasticsearchConnectionPoolSelectorsRoundRobinSelector',
];
// 服务提供者
class ElasticsearchService extends Service
{
public function register()
{
$this->app->bind('es', function(){
return ClientBuilder::create()
->setHosts(config('elasticsearch.hosts'))
->setRetries(config('elasticsearch.retries'))
->build();
});
}
}
2. 数据同步机制
// 商品模型观察者
class ProductObserver
{
public function saved(Product $product)
{
$params = [
'index' => 'products',
'id' => $product->id,
'body' => [
'title' => $product->title,
'description' => $product->description,
'price' => $product->price,
'categories' => $product->categories,
'created_at' => $product->created_at
]
];
app('es')->index($params);
}
public function deleted(Product $product)
{
app('es')->delete([
'index' => 'products',
'id' => $product->id
]);
}
}
3. 高级搜索实现
class SearchService
{
public function search($keyword, $filters = [])
{
$params = [
'index' => 'products',
'body' => [
'query' => [
'bool' => [
'must' => [
[
'multi_match' => [
'query' => $keyword,
'fields' => ['title^3', 'description'],
'type' => 'most_fields'
]
}
],
'filter' => $this->buildFilters($filters)
]
],
'highlight' => [
'fields' => [
'title' => new stdClass(),
'description' => new stdClass()
]
]
]
];
return app('es')->search($params);
}
protected function buildFilters($filters)
{
// 构建价格区间、分类等过滤条件
}
}
三、性能优化方案
- 索引设计:按业务分片+副本配置
- 查询优化:使用bool查询替代高开销操作
- 缓存策略:高频搜索词结果缓存
- 异步同步:队列处理数据变更
搜索性能对比
测试数据集:1000万商品
MySQL LIKE查询:1200-1500ms
Elasticsearch查询:15-50ms
TP内置搜索:200-300ms
四、扩展功能实现
1. 搜索建议(Completion Suggester)
// 创建建议器索引
PUT /products
{
"mappings": {
"properties": {
"suggest": {
"type": "completion"
}
}
}
}
// PHP实现
public function suggest($keyword)
{
$params = [
'index' => 'products',
'body' => [
'suggest' => [
'product_suggest' => [
'prefix' => $keyword,
'completion' => [
'field' => 'suggest'
]
]
]
]
];
return app('es')->search($params);
}