使用 Laravel Scout 数据库驱动搜索 Eloquent 关系的实用指南

发布于 作者:

A practical guide to search Eloquent relationships using Laravel Scout Database Driver image

Laravel Scout 是一个用于为您的 Laravel 应用程序添加全文搜索功能的工具。它使用 Algolia、Meilisearch、SQL 数据库等驱动程序来搜索您的 Eloquent 模型。该包高度可定制,使其成为在您的应用程序中实现搜索功能的多功能选项。

让我们检查一下如何使用 Laravel Scout 和数据库驱动程序搜索 Eloquent 模型关系。请记住,Laravel Scout 驱动程序当前支持 MySQL 和 PostgreSQL。

让我们首先创建一个新的 Laravel 应用程序。为此,您可以查看 Laravel 文档.

创建模型和迁移

我们将使用两个 Eloquent 模型

  • 帖子
  • 类别

创建类别模型

运行以下命令以创建 Category 模型

php artisan make:model Category -m

此命令将在 app\Models 目录中创建一个新的 Category 模型类,并在数据库中生成一个用于创建 categories 表的迁移文件。

打开 database/migrations 目录中的迁移文件,并添加 categories 表所需的列。例如

public function up()
{
Schema::create('categories', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->timestamps();
});
}

创建帖子模型

运行以下命令以创建 Post 模型

php artisan make:model Post -m

该命令将在 app\Models 目录中创建一个新的 Post 模型类,并在数据库中生成一个用于创建 posts 表的迁移文件。

打开 database/migrations 目录中的迁移文件,并添加 posts 表所需的列。例如

public function up()
{
Schema::create('posts', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->text('body');
$table->foreignId('category_id')->constrained();
$table->timestamps();
});
}

应用迁移

假设您已为应用程序配置了数据库,请运行以下命令以应用迁移并在数据库中创建 posts 和 categories 表

php artisan migrate

使用数据库种子器生成虚拟数据

让我们创建一个数据库种子器,以生成 posts 和 categories 表的一些虚拟记录。

首先,通过运行以下 artisan 命令创建一个新的种子器类

php artisan make:seeder PostsCategoriesTableSeeder

打开位于 database/seeds 目录中的 PostsCategoriesTableSeeder 类,并将 run 方法更新为以下代码

<?php
 
namespace Database\Seeders;
 
use Illuminate\Database\Console\Seeds\WithoutModelEvents;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\DB;
 
class PostsCategoriesTableSeeder extends Seeder
{
use WithoutModelEvents;
 
public function run()
{
// Generate 5 categories
$data = [
['name' => 'News'],
['name' => 'Sports'],
['name' => 'Entertainment'],
['name' => 'Technology'],
['name' => 'Business'],
];
 
DB::table('categories')->insert($data);
 
// Generate 1000 posts
for ($i = 1; $i <= 1000; $i++) {
DB::table('posts')->insert([
'title' => "Post $i",
'body' => "Content for post $i",
'category_id' => rand(1, 5)
]);
}
}
}

此种子器类生成五个虚拟类别和 1000 个虚拟帖子。每个类别的名称都是使用字符串和自动递增的 id 值的串联生成的,每个帖子的标题、正文和 category_id 是使用类似的方法生成的。category_id 是从类别列表中随机选择的。

要运行种子器,请将以下行添加到位于 database/seeds 目录中的 DatabaseSeeder 类的 run 方法中

$this->call(PostsCategoriesTableSeeder::class);

通过执行以下 artisan 命令运行种子器

php artisan db:seed

就是这样!现在,您有一个新的 Laravel 应用程序,其中包含 PostCategory 模型,以及已播种的虚拟数据。

配置应用程序以使用 Laravel Scout

要配置 Laravel 应用程序以使用 Laravel Scout 和数据库驱动程序,您需要按照以下步骤操作

首先,安装 Laravel Scout 包

composer require laravel/scout

接下来,发布 Scout 配置文件

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"

现在在 .env 文件中,将 SCOUT_DRIVER 选项设置为 database

SCOUT_DRIVER=database

接下来,将 Laravel\Scout\Searchable 特性添加到您的模型中,以使其可搜索

<?php
 
namespace App\Models;
 
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Laravel\Scout\Searchable;
 
class Post extends Model
{
use HasFactory;
use Searchable;
}

之后,在 Post 模型上定义 category() 关系,如下所示

public function category()
{
return $this->belongsTo(Category::class);
}

最后,在您的模型上定义 toSearchableArray() 方法,以指定 Laravel Scout 应该索引哪些字段

public function toSearchableArray()
{
return [
'title' => '',
'body' => '',
'categories.name' => '',
];
}

要使用 Laravel Scout 对您的模型执行全文搜索,您需要在您的模型上定义一个 toSearchableArray() 方法。此方法应返回一个 Laravel Scout 应该索引的数据数组。

toSearchableArray() 方法应包含与搜索查询相关的数据。例如,如果您正在搜索属于特定类别的帖子,则可以在 toSearchableArray() 方法中包含 Category 模型的 name 字段。

就是这样!您现在应该能够使用 Laravel Scout 使用数据库驱动程序对您的模型执行全文搜索。

让我们搜索。

首先,创建一个新的 SearchController 来测试查询。

创建控制器

运行以下命令

php artisan make:controller SearchController --invokable

这将在 app/Http/Controllers 目录中创建一个新的 SearchController 类。控制器类将包含一个名为 __invoke() 的方法,该方法在调用控制器时被调用。

添加路由

要将 SearchController 用于您的应用程序,您需要在 routes/web.php 文件中为其定义一个路由

Route::get('/search', SearchController::class);

此路由将 GET 请求映射到 /search URL,以映射到 SearchController 的 __invoke() 方法。

编写搜索查询

打开 SearchController 类,并使用 Laravel Scout 添加我们的第一个查询。

<?php
 
namespace App\Http\Controllers;
 
use App\Models\Post;
use Illuminate\Http\Request;
 
class SearchController extends Controller
{
public function __invoke(Request $request)
{
$posts = Post::search(trim($request->get('search')) ?? '')
->query(function ($query) {
$query->join('categories', 'posts.category_id', 'categories.id')
->select(['posts.id', 'posts.title', 'posts.body', 'categories.name as category'])
->orderBy('posts.id', 'DESC');
})
->get();
 
return response()->json(data: $posts, status: 200);
}
}

Post::search() 方法在 posts 数据库表上启动搜索查询。此方法返回 Builder 类 的实例。这意味着在通过 DatabaseEngine 实际执行查询之前,您可以应用一些函数,例如 where()whereIn()onlyTrashed()orderBy()take()paginate() 以及其他函数来进一步筛选您的结果。

trim($request->get('search')) ?? '' 输入参数从 HTTP 请求中检索查询字符串 search,并修剪任何前导或尾随空格,如果搜索查询字符串不存在,则返回一个空字符串。

query() 函数允许您通过定义附加约束或修改查询的 SELECT 子句来自定义搜索查询。在这种情况下,查询使用 JOIN 子句与 categories 表联接,以搜索 posts 表列以及 categories 表的 name 列。此外,我通过用数据库名称加前缀列并添加 ORDER BY 子句(指定完整列名称,包括数据库表)来显式选择要返回的列。在没有对数据库表名称加前缀的情况下,查询将失败。

最后,get() 方法用于执行搜索查询并从数据库中检索匹配的帖子。

让我们在浏览器中运行应用程序,并提供值为“technology”的 search 查询字符串,以返回所有类别为“technology”的帖子。

结果的第一部分。

结果的最后部分。

让我们针对数据库运行一个查询,以检索类别为“Technology”的帖子,并进行比较。

相同查询的数据库结果。

如您所见,两者都返回相同的结果!

如您所见,search() 方法上的 query() 函数是搜索 Laravel Scout 数据库驱动程序中的关系的强大工具。

您可以在 GitHub 上下载源代码的副本。

Bilal Haidar photo

您好 👋!我是 Bilal,Let's Remote 的创始人兼首席执行官。我是一名经验丰富的 Web 开发人员,拥有 16 年以上的经验。Laravel 是我的看家本领。

归档于
Cube

Laravel 新闻

加入 40,000 多名其他开发人员,绝不错过新的技巧、教程等。

Laravel Forge logo

Laravel Forge

轻松创建和管理您的服务器,并在几秒钟内部署您的 Laravel 应用程序。

Laravel Forge
Tinkerwell logo

Tinkerwell

Laravel 开发人员必备的代码运行器。使用 AI、自动完成和对本地和生产环境的即时反馈进行调试。

Tinkerwell
No Compromises logo

绝不妥协

Joel 和 Aaron,来自“绝不妥协”播客的两位经验丰富的开发者,现已可以为您的 Laravel 项目提供服务。 ⬧ 每月 7500 美元的固定价格。 ⬧ 无需冗长的销售流程。 ⬧ 无需合同。 ⬧ 100% 退款保证。

绝不妥协
Kirschbaum logo

Kirschbaum

提供创新和稳定性,确保您的 Web 应用程序取得成功。

Kirschbaum
Shift logo

Shift

运行旧的 Laravel 版本?即时、自动化的 Laravel 升级和代码现代化,让您的应用程序保持新鲜。

Shift
Bacancy logo

Bacancy

只需每月 2500 美元,即可用经验丰富的 Laravel 开发人员(拥有 4-6 年经验)为您的项目增光添彩。获得 160 小时的专项专业知识和 15 天的无风险试用期。立即安排通话!

Bacancy
Lucky Media logo

Lucky Media

现在就来体验 Lucky - Laravel 开发的理想选择,拥有十多年的经验!

Lucky Media
Lunar: Laravel E-Commerce logo

Lunar: Laravel 电子商务

Laravel 的电子商务。一个开源软件包,将现代无头电子商务功能的力量带到 Laravel。

Lunar: Laravel 电子商务
LaraJobs logo

LaraJobs

官方 Laravel 职位板

LaraJobs
SaaSykit: Laravel SaaS Starter Kit logo

SaaSykit:Laravel SaaS 启动工具包

SaaSykit 是一个 Laravel SaaS 启动工具包,它包含运行现代 SaaS 所需的所有功能。支付、精美结账、管理面板、用户仪表盘、身份验证、现成组件、统计数据、博客、文档等。

SaaSykit:Laravel SaaS 启动工具包
Rector logo

Rector

您无缝升级 Laravel 的合作伙伴,降低成本,加速创新,帮助企业取得成功

Rector
MongoDB logo

MongoDB

通过将 MongoDB 与 Laravel 強力整合,增强您的 PHP 应用程序,使开发人员能够轻松高效地构建应用程序。支持事务、搜索、分析和移动用例,同时使用熟悉的 Eloquent API。探索 MongoDB 的灵活、现代数据库如何改变您的 Laravel 应用程序。

MongoDB
Maska is a Simple Zero-dependency Input Mask Library image

Maska 是一个简单的零依赖输入掩码库

阅读文章
Add Swagger UI to Your Laravel Application image

将 Swagger UI 添加到您的 Laravel 应用程序

阅读文章
Assert the Exact JSON Structure of a Response in Laravel 11.19 image

在 Laravel 11.19 中断言响应的精确 JSON 结构

阅读文章
Build SSH Apps with PHP and Laravel Prompts image

使用 PHP 和 Laravel Prompts 构建 SSH 应用程序

阅读文章
Building fast, fuzzy site search with Laravel and Typesense image

使用 Laravel 和 Typesense 构建快速、模糊的网站搜索

阅读文章
Add Comments to your Laravel Application with the Commenter Package image

使用 Commenter 软件包为您的 Laravel 应用程序添加评论

阅读文章