جستجوی تمام متن در لاراول با Scout — به زبان ساده
جستجوی تمام متن یک قابلیت ضروری جهت فراهم ساختن امکان حرکت در میان صفحههای وبسایتهای با محتوای گسترده است. در این مقاله، شیوه پیادهسازی امکان جستجوی تمام متن را برای یک اپلیکیشن لاراول بررسی میکنیم. در واقع ما از کتابخانه Scout لاراول استفاده میکنیم که پیادهسازی جستجوی تمام متن را به امری ساده و جذاب تبدیل کرده است.
مستندات رسمی، کتابخانه Scout لاراول را به صورت زیر توصیف میکنند:
کتابخانه Scout لاراول یک راهحل ساده و مبتنی بر درایور برای افزودن امکان جستجوی تمام متن به مدلهای Eloquent ارائه میکند. Scout با استفاده از «مشاهدهگرهای مدل» (model observers) به طور خودکار اندیسهای جستجو را در وضعیتی همگامسازی شده با رکوردهای Eloquent حفظ میکند.
کتابخانه Scout لاراول به مدیریت دستکاری اندیسها در زمان بروز تغییراتی در دادههای مدل میپردازد. جایی که دادهها اندیس میشوند به درایوری وابسته است که برای کتابخانه Scout پیکربندیشده است.
در حال حاضر کتابخانه Scout از Algolia پشتیبانی میکند که یک API موتور جستجوی مبتنی بر کلود است و ما نیز در این مقاله از آن برای نمایش پیادهسازی جستجوی تمام متن استفاده خواهیم کرد.
ما کار خود را با نصب کتابخانههای Scout و Algolia server آغاز میکنیم و در ادامه برخی مثالهای واقعی را بررسی میکنیم که شیوه اندیسگذاری و جستجوی دادهها را نمایش میدهد.
پیکربندی سرور
در این بخش ما قصد داریم وابستگیهایی را که برای کار کردن کتابخانه Scout با لاراول لازم هستند نصب کنیم. پس از نصب، باید کمی آن را پیکربندی کنیم تا لاراول بتواند کتابخانه Scout را تشخیص دهد.
در ادامه کتابخانه Scout را با استفاده از Composer نصب میکنیم:
$composer require laravel/scout
اگر صرفاً خواسته باشیم کتابخانه Scout را نصب کنیم، کار به همین سادگی است. اینک که کتابخانه Scout نصب شده است، ابتدا باید مطمئن شویم که لاراول در مورد آن اطلاع دارد.
در صورتی که با لاراول کار کرده باشید، احتمالاً با مفهوم «ارائهدهنده سرویس» (service provider) که امکان پیکربندی سرویسها در اپلیکیشن را میدهد، آشنا هستید. بدین ترتیب هر زمان که بخواهید یک سرویس جدید را در اپلیکیشن لاراول پیکربندی کنید، کافی است یک مدخل ارائهدهنده سرویس مرتبط را در config/app.php اضافه کنید.
اگر با مفهوم ارائهدهنده سرویس در لاراول آشنا نیستید؛ قویاً توصیه میکنیم که ابتدا به طور کامل با این مفهوم آشنا شوید.
در مورد اپلیکیشنی که میخواهیم طراحی بکنیم باید یک ارائهدهنده سرویس به نام ScoutServiceProvider را به فهرست ارائهدهندههای سرویس در فایل config/app.php اضافه کنیم. روش کار در قطعه کد زیر نمایش یافته است:
1...
2...
3'providers' => [
4
5 /*
6 * Laravel Framework Service Providers...
7 */
8 Illuminate\Auth\AuthServiceProvider::class,
9 Illuminate\Broadcasting\BroadcastServiceProvider::class,
10 Illuminate\Bus\BusServiceProvider::class,
11 Illuminate\Cache\CacheServiceProvider::class,
12 Illuminate\Foundation\Providers\ConsoleSupportServiceProvider::class,
13 Illuminate\Cookie\CookieServiceProvider::class,
14 Illuminate\Database\DatabaseServiceProvider::class,
15 Illuminate\Encryption\EncryptionServiceProvider::class,
16 Illuminate\Filesystem\FilesystemServiceProvider::class,
17 Illuminate\Foundation\Providers\FoundationServiceProvider::class,
18 Illuminate\Hashing\HashServiceProvider::class,
19 Illuminate\Mail\MailServiceProvider::class,
20 Illuminate\Notifications\NotificationServiceProvider::class,
21 Illuminate\Pagination\PaginationServiceProvider::class,
22 Illuminate\Pipeline\PipelineServiceProvider::class,
23 Illuminate\Queue\QueueServiceProvider::class,
24 Illuminate\Redis\RedisServiceProvider::class,
25 Illuminate\Auth\Passwords\PasswordResetServiceProvider::class,
26 Illuminate\Session\SessionServiceProvider::class,
27 Illuminate\Translation\TranslationServiceProvider::class,
28 Illuminate\Validation\ValidationServiceProvider::class,
29 Illuminate\View\ViewServiceProvider::class,
30
31 /*
32 * Package Service Providers...
33 */
34 Laravel\Tinker\TinkerServiceProvider::class,
35
36 /*
37 * Application Service Providers...
38 */
39 App\Providers\AppServiceProvider::class,
40 App\Providers\AuthServiceProvider::class,
41 App\Providers\BroadcastServiceProvider::class,
42 App\Providers\EventServiceProvider::class,
43 App\Providers\RouteServiceProvider::class,
44 Laravel\Scout\ScoutServiceProvider::class,
45],
46...
47...
اینک لاراول از وجود ارائهدهنده سرویسی به نام ScoutServiceProvider آگاهی دارد. کتابخانه Scout به همراه یک فایل پیکربندی ارائه میشود که به ما امکان تنظیم نام کاربری و رمز عبور API را میدهد.
در ادامه فایلهای ارائه شده از سوی Scout را با استفاده از دستور زیر منتشر میکنیم:
1$ php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
2Copied File [/vendor/laravel/scout/config/scout.php] To [/config/scout.php]
3Publishing complete.
همان طور که میبینید بدین ترتیب فایل vendor/laravel/scout/config/scout.php به مسیر config/scout.php کپی شده است.
حساب کاربری Algolia
در ادامه یک حساب کاربری در سرویس Algolia (+) ایجاد میکنیم، چون به نام کاربری و رمز عبور API آن نیاز داریم. زمانی که اطلاعات API را به دست آوردید میتوانید اقدام به پیکربندی تنظیمات مورد نیاز در فایل config/scout.php به شیوهای که در قطعه کد زیر نمایش یافته است، بکنید:
1<?php
2
3return [
4
5 /*
6 |--------------------------------------------------------------------------
7 | Default Search Engine
8 |--------------------------------------------------------------------------
9 |
10 | This option controls the default search connection that gets used while
11 | using Laravel Scout. This connection is used when syncing all models
12 | to the search service. You should adjust this based on your needs.
13 |
14 | Supported: "algolia", "null"
15 |
16 */
17
18 'driver' => env('SCOUT_DRIVER', 'algolia'),
19
20 /*
21 |--------------------------------------------------------------------------
22 | Index Prefix
23 |--------------------------------------------------------------------------
24 |
25 | Here you may specify a prefix that will be applied to all search index
26 | names used by Scout. This prefix may be useful if you have multiple
27 | "tenants" or applications sharing the same search infrastructure.
28 |
29 */
30
31 'prefix' => env('SCOUT_PREFIX', ''),
32
33 /*
34 |--------------------------------------------------------------------------
35 | Queue Data Syncing
36 |--------------------------------------------------------------------------
37 |
38 | This option allows you to control if the operations that sync your data
39 | with your search engines are queued. When this is set to "true" then
40 | all automatic data syncing will get queued for better performance.
41 |
42 */
43
44 'queue' => env('SCOUT_QUEUE', false),
45
46 /*
47 |--------------------------------------------------------------------------
48 | Chunk Sizes
49 |--------------------------------------------------------------------------
50 |
51 | These options allow you to control the maximum chunk size when you are
52 | mass importing data into the search engine. This allows you to fine
53 | tune each of these chunk sizes based on the power of the servers.
54 |
55 */
56
57 'chunk' => [
58 'searchable' => 500,
59 'unsearchable' => 500,
60 ],
61
62 /*
63 |--------------------------------------------------------------------------
64 | Soft Deletes
65 |--------------------------------------------------------------------------
66 |
67 | This option allows you to control whether to keep soft deleted records in
68 | the search indexes. Maintaining soft deleted records can be useful
69 | if your application still needs to search for the records later.
70 |
71 */
72
73 'soft_delete' => false,
74
75 /*
76 |--------------------------------------------------------------------------
77 | Algolia Configuration
78 |--------------------------------------------------------------------------
79 |
80 | Here you may configure your Algolia settings. Algolia is a cloud hosted
81 | search engine which works great with Scout out of the box. Just plug
82 | in your application ID and admin API key to get started searching.
83 |
84 */
85
86 'algolia' => [
87 'id' => env('ALGOLIA_APP_ID', 'STQK4DEGMA'),
88 'secret' => env('ALGOLIA_SECRET', '6ef572194f70201ed7ad102cc9f90e05'),
89 ],
90
91];
دقت داشته باشید که ما مقدار SCOUT_DRIVER را برابر با درایور algolia تعیین کردهایم. از این رو لازم است که تنظیمات لازم برای درایور Algolia را در انتهای فایل پیکربندی کنید. بدین منظور کافی است مقدار id و secret را که از حساب کاربری Algolia دریافت کردهاید تنظیم کنید.
همان طور که شاهد هستید، ما مقادیر را از متغیرهای محیطی واکشی کردهایم، بنابراین باید مطمئن شویم که متغیرهای زیر را در فایل env. به صورت صحیحی تعیین کردهایم:
1...
2...
3ALGOLIA_APP_ID=STQK4DEGMA
4ALGOLIA_SECRET=6ef572194f70201ed7ad102cc9f90e05
5...
6...
درنهایت باید SDK مربوط به Algolia PHP را نصب کنیم که برای تعامل با Algolia از طریق API-ها ضروری است. آن را با استفاده از composer و به صورت زیر نصب میکنیم:
1$composer require algolia/algoliasearch-client-php
بدین ترتیب ما همه وابستگیهای لازم برای ارسال و اندیس کردن دادهها در سرویس algolia را در اختیار داریم.
ایجاد قابلیت اندیسگذاری و جستجو در مدلها
در بخش قبلی ما همه کارهایی را که برای راهاندازی کتابخانههای Scout و Algolia لازم بود انجام دادیم و از این رو اینک میتوانیم دادهها را با استفاده از سرویس جستجوی Algolia اندیسگذاری و جستجو کنیم.
در این بخش مثالی را بررسی میکنیم که شیوه اندیس کردن دادههای موجود و بازیابی نتایج جستجو از Algolia را نمایش میدهد. تصور ما بر این است که شما مدل Post پیشفرض را در اپلیکیشن خود دارید و در مثال خود نیز از آن استفاده خواهیم کرد.
نخستین کاری که باید انجام دهیم، افزودن خصیصه Laravel\Scout\Searchable به مدل Post است. بدین ترتیب مدل Post قابل جستجو میشود و لاراول رکوردهای پست را هر بار که یک رکورد پست، اضافه، بهروزرسانی یا حذف میشود، با اندیس Algolia همگامسازی میکند.
1<?php
2namespace App;
3
4use Illuminate\Database\Eloquent\Model;
5use Laravel\Scout\Searchable;
6
7class Post extends Model
8{
9 use Searchable;
10
11 /**
12 * The attributes that should be mutated to dates.
13 *
14 * @var array
15 */
16 protected $dates = [
17 'created_at',
18 'updated_at'
19 ];
20}
بدین ترتیب مدل Post برای جستجو مناسبسازی میشود. در ادامه و در وهله نخست فیلدهایی را که میبایست اندیسگذاری شوند پیکربندی کنیم. البته لازم نیست همه فیلدهای مدل را در Algolia اندیسگذاری کنید و بهتر است آن را سبک و کارآمد نگه داریم. در واقع در اغلب موارد به چنین کاری نیاز هم نداریم.
میتوان toSearchableArray را در کلاس مدل اضافه کرد تا فیلدهایی که قرار است اندیسگذاری شوند، پیکربندی شوند.
1/**
2 * Get the indexable data array for the model.
3 *
4 * @return array
5 */
6public function toSearchableArray()
7{
8 $array = $this->toArray();
9
10 return array('id' => $array['id'],'name' => $array['name']);
11}
اکنون آماده ایمپورت و اندیسگذاری رکوردهای موجود Post در Algolia هستیم. در واقع کتابخانه Scout این کار را از طریق ارائه دستور artisan زیر سادهتر ساخته است:
1$php artisan scout:import "App\Post"
این دستور همه رکوردهای مدل Post را در یک حرکت ایمپورت میکند. همه آنها به محض ایمپورت شدن، اندیسگذاری میشوند و از این رو در این لحظه آماده کوئری زدن هستند. در ادامه داشبورد Algolia را بررسی کنید تا رکوردهای ایمپورت شده و دیگر ابزارها را مشاهده کنید.
جمعبندی طرز کار Scout
در این بخش مثالی را ارائه میکنیم که شیوه اجرای عمل جستجو و عملیات CRUD را که به صورت آنی با اندیس Algolia همگامسازی شدهاند نمایش میدهد.
در این بخش فایل app/Http/Controllers/SearchController.php را با محتوای زیر ایجاد میکنیم:
1<?php
2namespace App\Http\Controllers;
3
4use App\Http\Controllers\Controller;
5use App\Post;
6
7class SearchController extends Controller
8{
9 public function query()
10 {
11 // queries to Algolia search index and returns matched records as Eloquent Models
12 $posts = Post::search('title')->get();
13
14 // do the usual stuff here
15 foreach ($posts as $post) {
16 // ...
17 }
18 }
19
20 public function add()
21 {
22 // this post should be indexed at Algolia right away!
23 $post = new Post;
24 $post->setAttribute('name', 'Another Post');
25 $post->setAttribute('user_id', '1');
26 $post->save();
27 }
28
29 public function delete()
30 {
31 // this post should be removed from the index at Algolia right away!
32 $post = Post::find(1);
33 $post->delete();
34 }
35}
البته ما باید مسیرهای مرتبط را نیز اضافه کنیم:
یه سوال دارم آیا برای پروژه های فروشگاهی و هر پروژه ای که نیاز به اندیس گذاری برای سرچ داره آیا از این اسکات باید استفاده کرد
و اینکه آیا اسکات پولی هست برای این عملیات کراد و موارد دیگه؟
فرق اسکات با الستیک سرچ چیه؟