Tìm Kiếm Siêu Tốc Với Laravel Scout và Meilisearch
User::where('name', 'like', '%john%')->get() ổn cho 100 người dùng.
Với 100,000 người dùng, nó chậm.
Và nếu người dùng gõ "Jonh", nó không trả về gì cả.
Laravel Scout cung cấp giải pháp dựa trên driver để thêm tìm kiếm full-text vào các models của bạn. Meilisearch là search engine mã nguồn mở, cực nhanh, kết hợp hoàn hảo với Laravel.
Tại Sao Cần Full-Text Search?
Truy vấn SQL LIKE truyền thống có nhiều hạn chế:
- Hiệu năng: Chúng quét toàn bộ bảng, chậm dần theo cấp số nhân khi dữ liệu tăng
- Không chịu lỗi đánh máy: "Jonh" sẽ không match với "John"
- Không xếp hạng độ liên quan: Kết quả không được sắp xếp theo mức độ phù hợp
- Không stemming: "running" sẽ không match với "run"
Search engine full-text giải quyết tất cả vấn đề này bằng cách xây dựng inverted index và sử dụng các thuật toán tinh vi.
Cài Đặt
- Cài đặt Scout:
composer require laravel/scout
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
- Cài đặt Meilisearch Driver:
composer require meilisearch/meilisearch-php http-interop/http-factory-guzzle
- Cấu hình
.env:
SCOUT_DRIVER=meilisearch
MEILISEARCH_HOST=http://127.0.0.1:7700
MEILISEARCH_KEY=your-master-key
Cấu Hình
Thêm trait Searchable vào model của bạn.
use Laravel\Scout\Searchable;
class Post extends Model
{
use Searchable;
// Tùy chọn: Tùy chỉnh dữ liệu nào được index
public function toSearchableArray()
{
return [
'id' => $this->id,
'title' => $this->title,
'content' => strip_tags($this->content),
'author' => $this->author->name,
'tags' => $this->tags->pluck('name')->toArray(),
'published_at' => $this->published_at?->timestamp,
];
}
// Tùy chỉnh tên search index
public function searchableAs(): string
{
return 'posts_index';
}
}
Chạy Meilisearch
Cách dễ nhất là qua Laravel Sail (Docker):
# docker-compose.yml
meilisearch:
image: 'getmeili/meilisearch:latest'
ports:
- '7700:7700'
environment:
- MEILI_MASTER_KEY=your-master-key
volumes:
- 'sail-meilisearch:/meili_data'
Hoặc cài đặt local trên macOS:
brew install meilisearch
meilisearch --master-key="your-master-key"
Index Dữ Liệu
Đẩy dữ liệu hiện có của bạn tới search engine:
php artisan scout:import "App\Models\Post"
Để re-index sau khi thay đổi schema:
php artisan scout:flush "App\Models\Post"
php artisan scout:import "App\Models\Post"
Tìm Kiếm
Bây giờ thay thế các truy vấn tiêu chuẩn của bạn bằng truy vấn Scout:
// SQL tiêu chuẩn (Chậm, nghiêm ngặt)
Post::where('title', 'like', '%larvel%')->get(); // Không trả về gì
// Scout (Nhanh, chịu lỗi đánh máy)
Post::search('larvel')->get(); // Trả về các posts 'Laravel'
Filters và Sorting
Scout hỗ trợ filtering và sorting thông qua các tính năng mạnh mẽ của Meilisearch:
// Filtering cơ bản
Post::search('tutorial')
->where('status', 'published')
->paginate(20);
// Nhiều filters
Post::search('laravel')
->where('category_id', 5)
->where('published_at', '>', now()->subMonth()->timestamp)
->get();
Cấu hình Filterable Attributes
Để sử dụng filters, bạn phải cấu hình Meilisearch:
// Trong AppServiceProvider hoặc một command
use Meilisearch\Client;
$client = new Client(config('scout.meilisearch.host'));
$client->index('posts_index')->updateFilterableAttributes([
'status',
'category_id',
'published_at',
'tags',
]);
$client->index('posts_index')->updateSortableAttributes([
'published_at',
'views_count',
]);
Phân Trang
Scout tích hợp mượt mà với pagination của Laravel:
$results = Post::search('laravel')->paginate(15);
// Trong Blade
@foreach($results as $post)
<h2>{{ $post->title }}</h2>
@endforeach
{{ $results->links() }}
Cập Nhật Real-Time
Scout tự động đồng bộ các thay đổi tới search index:
// Điều này tự động cập nhật search index
$post->update(['title' => 'Tiêu đề mới']);
// Điều này xóa khỏi search index
$post->delete();
Queue Index Updates
Để hiệu năng tốt hơn, đưa các index operations vào queue:
// config/scout.php
'queue' => true,
Meilisearch vs Algolia
| Tính năng | Meilisearch | Algolia |
|---|---|---|
| Giá | Miễn phí (self-hosted) | Trả phí theo search |
| Chịu lỗi đánh máy | ✅ | ✅ |
| Faceted search | ✅ | ✅ |
| Hosting | Self-hosted hoặc Cloud | Chỉ managed |
| Hiệu năng | Xuất sắc | Xuất sắc |
Với hầu hết dự án, Meilisearch mang lại sự cân bằng tốt nhất giữa tính năng và chi phí.
Best Practices
- Chỉ index nội dung có thể tìm kiếm: Không index passwords hoặc dữ liệu nhạy cảm
- Sử dụng queue cho datasets lớn: Tránh request timeout
- Cấu hình stop words: Loại trừ các từ phổ biến như "the", "và"
- Thiết lập synonyms: Map "JS" tới "JavaScript"
- Giám sát kích thước index: Giữ search data gọn gàng
Full-text search biến đổi trải nghiệm người dùng. Với Scout và Meilisearch, bạn có được khả năng tìm kiếm cấp doanh nghiệp mà không cần chi phí doanh nghiệp.