
LIKE操作符进行搜索,但这在数据达到一定规模后,性能瓶颈就暴露无遗。我尝试过优化SQL查询、添加索引,但效果甚微。我深知,要解决这个问题,需要引入专业的全文本搜索引擎。市面上不乏优秀的解决方案,比如Elasticsearch、Algolia等,但它们通常意味着更高的学习曲线、更复杂的部署和维护成本,这对于一个快速迭代的项目来说,无疑增加了额外的负担。我渴望找到一个既能提供高性能搜索,又能在Laravel生态中无缝集成、保持开发效率的方案。
Composer在线学习地址:学习地址
想象一下,当你的电商网站拥有成千上万件商品,或者博客系统积累了海量的文章,用户输入一个关键词进行搜索时:
SELECT * FROM products WHERE name LIKE '%关键词%' 这样的查询,在数据量大时,会导致全表扫描,效率极低。即使有索引,也难以覆盖所有模糊匹配场景。LIKE匹配无法理解语义,无法根据词频、位置等因素提供更相关的搜索结果。是不是感觉眼前一亮?我发现了一个完美的组合来解决这些痛点:Typesense 作为高性能的后端搜索引擎,以及 Laravel Scout 作为Laravel模型与搜索引擎之间的优雅桥梁。
Typesense 是一个现代化的、开源的、快速且容错的全文本搜索引擎。它的设计目标是提供与Algolia类似的开发者体验,但作为开源项目,它让你拥有完全的控制权。Typesense 的核心优势在于:
Laravel Scout 是 Laravel 官方提供的一个轻量级解决方案,用于为 Eloquent 模型添加全文本搜索。它的核心思想是提供一个统一的 API,让你可以在不修改应用代码逻辑的情况下,轻松切换不同的搜索驱动(如Algolia, Elasticsearch, MeiliSearch等)。Scout 的优点在于:
search() 方法。typesense/laravel-scout-typesense-driver:连接二者的桥梁最初,typesense/laravel-scout-typesense-driver 作为独立的 Composer 包提供了将 Typesense 集成到 Laravel Scout 的能力。但好消息是,它的核心功能已被原生集成到Laravel Scout中!这意味着现在你可以更无缝地享受 Typesense 带来的强大搜索体验,无需额外安装这个特定的驱动包(除非你需要一些高级的、非原生支持的特性,或者你正在使用较旧的Laravel版本)。
本文将以原生Laravel Scout集成Typesense的方式进行说明,但请注意,原始的typesense/laravel-scout-typesense-driver包的安装和配置方式与原生集成非常相似,它为原生支持奠定了基础。
Typesense PHP SDK 使用 httplug 来抽象 HTTP 客户端。你需要根据你的 guzzlehttp/guzzle 版本安装对应的 httplug 适配器。例如,如果你的 Laravel 项目使用 Guzzle 7 (Laravel 8+ 通常如此):
<code class="bash">composer require php-http/guzzle7-adapter</code>
如果你的项目还没有安装 Laravel Scout,请先安装它:
<code class="bash">composer require laravel/scout</code>
<code class="bash">php artisan vendor:publish --provider="LaravelScoutScoutServiceProvider"</code>
这会在 config/scout.php 文件中生成 Scout 的配置。
在你的 .env 文件中,指定 Scout 使用 Typesense 驱动:
<code class="dotenv">SCOUT_DRIVER=typesense</code>
然后,在 config/scout.php 文件中添加 Typesense 的配置信息。你需要确保 Typesense 服务正在运行。
<pre class="brush:php;toolbar:false;">// config/scout.php
return [
// ... 其他配置
'typesense' => [
'api_key' => env('TYPESENSE_API_KEY', 'your_typesense_api_key'), // 你的 Typesense API Key
'nodes' => [
[
'host' => env('TYPESENSE_HOST', 'localhost'),
'port' => env('TYPESENSE_PORT', '8108'),
'path' => env('TYPESENSE_PATH', ''),
'protocol' => env('TYPESENSE_PROTOCOL', 'http'),
],
],
'nearest_node' => [ // 可选,用于读操作的最近节点
'host' => env('TYPESENSE_NEAREST_HOST', 'localhost'),
'port' => env('TYPESENSE_NEAREST_PORT', '8108'),
'path' => env('TYPESENSE_NEAREST_PATH', ''),
'protocol' => env('TYPESENSE_NEAREST_PROTOCOL', 'http'),
],
'connection_timeout_seconds' => 2,
'healthcheck_interval_seconds' => 30,
'num_retries' => 3,
'retry_interval_seconds' => 1,
],
];建议将 api_key 和节点信息也放入 .env 文件,方便管理。
在你的 Eloquent 模型中,你需要使用 LaravelScoutSearchable trait,并实现 TypesenseLaravelTypesenseInterfacesTypesenseDocument 接口(这个接口在原生Scout中可能不再强制,但其方法是Typesense驱动所需的)。
<pre class="brush:php;toolbar:false;"><?php
namespace AppModels;
use IlluminateDatabaseEloquentModel;
use LaravelScoutSearchable;
use TypesenseLaravelTypesenseInterfacesTypesenseDocument; // 注意这个接口的引入
class Product extends Model implements TypesenseDocument
{
use Searchable;
/**
* 获取模型的可搜索数据数组。
*
* @return array
*/
public function toSearchableArray()
{
// 返回你希望 Typesense 索引的字段
return array_merge(
$this->toArray(),
[
'id' => (string) $this->id, // Typesense通常将ID视为字符串
'created_at' => $this->created_at->timestamp, // 将日期转换为时间戳
]
);
}
/**
* Typesense Collection 的 Schema 定义。
*
* @return array
*/
public function getCollectionSchema(): array
{
return [
'name' => $this->searchableAs(), // Collection 名称,通常是模型的表名
'fields' => [
['name' => 'id', 'type' => 'string'],
['name' => 'name', 'type' => 'string'],
['name' => 'description', 'type' => 'string'],
['name' => 'price', 'type' => 'float'],
['name' => 'created_at', 'type' => 'int64'],
],
'default_sorting_field' => 'created_at', // 默认排序字段
];
}
/**
* 定义 Typesense 搜索时要查询的字段。
*
* @return array
*/
public function typesenseQueryBy(): array
{
return [
'name',
'description',
];
}
}当模型准备好后,你需要将现有数据导入到 Typesense 中:
<code class="bash">php artisan scout:import "App\Models\Product"</code>
现在,你就可以像使用任何 Laravel Scout 驱动一样进行搜索了:
<pre class="brush:php;toolbar:false;">use AppModelsProduct;
// 简单搜索
$results = Product::search('手机')->get();
// 带有过滤和排序的搜索
$filteredResults = Product::search('笔记本')
->where('price', '<', 5000)
->orderBy('created_at', 'desc')
->paginate(10);
// 多重搜索 (Multi-Search)
// Typesense 驱动也支持 Laravel Scout 的 multi-search 功能
$searchRequests = [
['collection' => 'products', 'q' => '手机'],
['collection' => 'articles', 'q' => '编程'],
];
// 具体的实现方式可能需要查看 Typesense PHP SDK 或 Scout 扩展的文档
// 例如:Product::search('')->searchMulti($searchRequests)->paginateRaw();通过集成 Typesense 和 Laravel Scout,你的应用将获得:
LIKE查询的漫长等待,用户将体验到近乎实时的搜索响应。从最初的搜索性能瓶颈和复杂的集成困境,到如今通过 Typesense 和 Laravel Scout 提供的闪电般快速、智能且易于管理的全文本搜索体验,我的Laravel应用焕发了新的生机。这不仅极大地提升了用户满意度,也让开发团队从繁琐的搜索优化中解脱出来,专注于核心业务逻辑的开发。如果你也正在为 Laravel 应用的搜索性能而烦恼,那么 Typesense 与 Laravel Scout 的组合,绝对值得你一试!
以上就是如何在Laravel中实现高性能全文本搜索?Typesense与Scout驱动助你一臂之力!的详细内容,更多请关注php中文网其它相关文章!
Copyright 2014-2025 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号