在使用 Laravel 构建 Web 应用时,搜索功能几乎是不可或缺的一部分。Laravel Scout 提供了一个优雅的解决方案,让我们能够快速集成各种搜索驱动,其中 Elasticsearch 因其强大的性能和丰富的功能而备受青睐。然而,当你开始尝试构建更复杂的搜索逻辑时,可能会遇到一个令人沮丧的限制:Laravel Scout 官方文档明确指出,“更高级的
子句目前不受支持”。这意味着,除了简单的关键词模糊搜索和 ID 匹配之外,你很难直接通过 Scout 实现多条件组合、权重提升、范围查询等高级 Elasticsearch 特性。
想象一下这样的场景:你需要搜索已发布的文章,文章标题中必须包含某个词,内容中包含另一个词,同时如果文章带有“精选”标签,其搜索结果的权重还需要提高。面对这样的需求,Scout 默认的
显得力不从心,你可能不得不放弃 Scout,转而直接操作 Elasticsearch 客户端,这无疑增加了开发复杂度和维护成本。
Composer在线学习地址:
学习地址
告别束缚:jeroen-g/explorer 登场
正当许多开发者为此感到头疼时,
出现了。它是一款专为 Laravel Scout 设计的“下一代”Elasticsearch 驱动,旨在彻底解决 Scout 在高级查询方面的限制,让你能够充分发挥 Elasticsearch 强大的查询能力,而无需脱离 Scout 的优雅语法。
的核心理念是,将 Elasticsearch 原生的查询 DSL(Domain Specific Language)以更 Laravel 友好的方式融入 Scout 的查询构建器中,让你能够像操作 Eloquent 模型一样,轻松构建出复杂的搜索查询。
快速上手
安装
非常简单,通过 Composer 即可:
安装完成后,你需要发布其
配置文件
来定义你的索引映射:
别忘了按照 Laravel Scout 的安装说明进行操作,并在你的
配置文件中,将驱动设置为
:
灵活的索引配置
提供了两种定义索引映射的方式,你可以根据项目需求选择最适合你的:
在配置文件中集中定义:
你可以在
中为每个索引详细定义其属性映射:
在模型中定义:
如果你更倾向于将索引配置与模型紧密结合,可以直接在
中指定模型类,
会自动根据模型的字段生成映射。如果需要更精细的控制,你的模型可以实现
接口,并重写
方法来自定义映射。
突破限制:高级查询的艺术
现在,让我们回到之前提到的复杂搜索场景。使用
,你将能够以一种非常直观和强大的方式来实现它。
PHP 8.5.5
PHP 8.5.5 是 PHP 8.5 分支的维护更新版本。该版本延续了“小步快跑”的迭代逻辑,通过深度错误修复、底层性能微调以及安全加固,旨在为开发者提供一个更健壮、更高效的运行环境。该版本严格遵守语义化版本规范,不包含破坏性变更。
下载
假设我们需要获取所有满足以下条件的文章:
已发布 (
为
)
文档中包含“lorem”
标题中包含“ipsum”
如果带有“featured”标签,则其得分权重提高 2 倍
使用
,你可以这样构建查询:
是不是非常简洁和强大?
引入了
、
、
等方法,它们分别对应 Elasticsearch 的布尔查询上下文:
:查询必须匹配的条件,会影响得分。
:查询应该匹配的条件,匹配越多得分越高。
:查询必须匹配的条件,但不影响得分(常用于缓存优化)。
通过组合
(模糊匹配)、
(精确匹配)、
(多值精确匹配) 等查询对象,你几乎可以构建任何复杂的 Elasticsearch 查询,而无需离开 Laravel 的舒适区。
其他实用功能
还提供了一些实用的 Artisan 命令,例如直接通过命令行搜索索引:
总结与展望
彻底改变了 Laravel Scout 在 Elasticsearch 集成方面的游戏规则。它解决了长期以来困扰开发者的“高级查询限制”问题,让开发者能够:
充分利用 Elasticsearch 的强大功能:
无需学习复杂的 Elasticsearch DSL,即可通过 Laravel 友好的语法实现复杂的搜索逻辑。
提升搜索相关性和用户体验:
精准控制查询条件和权重,提供更符合用户预期的搜索结果。
简化开发和维护:
将搜索逻辑与应用代码紧密结合,减少了直接操作 Elasticsearch 客户端的复杂性。
保持 Scout 的优雅:
依然享受 Scout 带来的模型同步和统一接口的便利。
如果你正在使用 Laravel Scout 并且对 Elasticsearch 的高级查询功能有所渴望,那么
绝对是你不可错过的选择。它将让你的搜索功能从“能用”升级到“强大”,为你的应用带来质的飞跃。
wherePost::search('关键词')->get()jeroen-g/explorerexplorerjeroen-g/explorercomposer require jeroen-g/explorerphp artisan vendor:publish --tag=explorer.configconfig/scout.phpelastic// config/scout.php
'driver' => env('SCOUT_DRIVER', 'elastic'), // 确保这里是 'elastic'explorerconfig/explorer.phpreturn [
'indexes' => [
'posts_index' => [
'properties' => [
'id' => 'keyword',
'title' => 'text',
'published' => 'boolean',
'tags' => 'keyword',
],
]
]
];config/explorer.phpexplorerJeroenG\Explorer\Application\ExploredmappableAs()// config/explorer.php
return [
'indexes' => [
\App\Models\Post::class
],
];explorerpublishedtruejeroen-g/exploreruse App\Models\Post;
use JeroenG\Explorer\Application\Query\Matching;
use JeroenG\Explorer\Application\Query\Term;
use JeroenG\Explorer\Application\Query\Terms;
$posts = Post::search('lorem') // 默认的模糊搜索,搜索文档中包含“lorem”
->must(new Matching('title', 'ipsum')) // 标题中必须包含“ipsum”
->should(new Terms('tags', ['featured'], 2)) // 如果标签是“featured”,提升权重2倍
->filter(new Term('published', true)) // 过滤条件:必须是已发布的
->get();explorermustshouldfiltermust()should()filter()MatchingTermTermsexplorerphp artisan elastic:search "App\Models\Post" loremjeroen-g/explorerjeroen-g/explorer