Scout full text search
- Queue
- Driver necessary conditions
- Algolia
- Configure model ID
- ##Index
- Batch import
- Add records
- Add by query
- Update record
- Delete record Conditional Search model instance
- Search
- Where statement
- Paging
- Soft delete
- Custom engine
- Write engine
- Register engine
- Generate macro command
Laravel Scout
Introduction
Laravel Scout provides a driver-based full-text search for Eloquent models simple solution. By using model observers, Scout automatically synchronizes the search index of Eloquent records.
Currently, Scout comes with a Algolia driver. However, writing a custom driver is also easy, and you can easily extend Scout with your own search implementation.
##InstallationFirst, install Scout through the Composer package manager:composer require laravel/scout
Scout After the installation is complete, use thevendor:publish
Artisan command to generate the Scout configuration file. This command will generate a
scout.phpconfiguration file in your
configdirectory.
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
Finally, add theLaravel\Scout\Searchable
trait to the model you want to search. This trait will register a model observer to keep the model and all drivers synchronized:
<?php namespace App; use Laravel\Scout\Searchable; use Illuminate\Database\Eloquent\Model; class Post extends Model{ use Searchable; }
QueueAlthough It is not mandatory to use Scout, but before using this library, it is strongly recommended that you configure a queue driver and use it to run a queue to handle all operations that allow Scout to synchronize model information to the search index, providing more information for your application's web interface. Quick response. Once you have configured the queue driver, the value of thequeue
option in your
config/scout.phpconfiguration file should be set to
true:
'queue' => true,
Driver necessary conditions
Algolia
When using the Algolia driver, you need to configure your Algolia in the
config/scout.php
configuration fileid
andsecret
credentials. After configuring the credentials, you also need to use the Composer package manager to install the Algolia PHP SDK:composer require algolia/algoliasearch-client-php:^2.2
##ConfigurationConfigure model indexEach Eloquent model is synchronized through a given "index", which contains all searchable model records. In other words, you can think of each "index" as a MySQL data table. By default, each model is persisted to an index that matches the model's "table" name (usually the plural form of the model name). You can also customize the index of the model by overriding thesearchableAs
method on the model:
<?php namespace App; use Laravel\Scout\Searchable; use Illuminate\Database\Eloquent\Model; class Post extends Model{ use Searchable; /** * 获取索引名称 * * @return string */ public function searchableAs() { return 'posts_index'; } }
Configurable Search Data By default, models are persisted to the search index in the fulltoArray
format. If you want to customize the data synchronized to the search index, you can override the
toSearchableArraymethod on the model:
<?php namespace App; use Laravel\Scout\Searchable; use Illuminate\Database\Eloquent\Model; class Post extends Model{ use Searchable; /** * 获取模型的可搜索数据 * * @return array */ public function toSearchableArray() { $array = $this->toArray(); // Customize array... return $array; } }
Configuring Model IDBy default, Scout will use the model's primary key as the unique ID stored in the search index. Can be customized through thegetScoutKey
method on the model:
<?php namespace App; use Laravel\Scout\Searchable; use Illuminate\Database\Eloquent\Model; class User extends Model{ use Searchable; /** * 获取模型主键 * * @return mixed */ public function getScoutKey() { return $this->email; } }
IndexBatch ImportIf you want to install Scout into an existing project, you may already have database records that you want to import into the search driver. Scout provides the Artisan commandimport
to import all existing records into the search index: the
php artisan scout:import "App\Post"
flush
command can be used to delete all model records from the search index. :
php artisan scout:flush "App\Post"
Add recordWhen you add theLaravel\Scout\Searchable trait
To a model, all you need to do is
savea model instance and it will automatically be added to the search index. If you have configured Scout to
use a queue, then this operation will be performed in the background by your queue worker process:$order = new App\Order;// ...$order->save();
Add via query
If you want to add a collection of models to the search index via the Eloquent query builder, you can also chain the
searchable
method on the Eloquent query builder.searchable
will chunk the constructor's query results and add the records to your search index. Likewise, if you have configured Scout to use a queue, all data chunks will be added in the background by your queue worker process:// 通过 Eloquent 查询构造器增加.. App\Order::where('price', '>', 100)->searchable(); // 你也可以通过模型关系增加记录... $user->orders()->searchable(); // 你也可以通过集合增加记录... $orders->searchable();
searchable
method can be thought of as an "update" Insert" operation. In other words, if the model record is already in your index, it will be updated. If it does not exist in the search index, it is added to the index.Update Record
To update a searchable model, simply update the properties of the model instance and add the model
save
to database. Scout will automatically sync updates to your search index:$order = App\Order::find(1); // 更新订单... $order->save();
You can also use the
searchable
method on an Eloquent query to update a collection of models. If this model does not exist in the index you are searching for, it will be created:// 通过 Eloquent 查询更新... App\Order::where('price', '>', 100)->searchable(); // 你也可以通过数据间的关联进行更新... $user->orders()->searchable(); // 你也可以通过数据集合进行更新... $orders->searchable();
Delete record
Use
delete
Delete the model from the database to remove the records in the index. This form of deletion is even compatible with the soft-delete model:$order = App\Order::find(1); $order->delete();
If you do not want the record to be retrieved before deletion, you can use the
unsearchable
method on the Eloquent query instance or collection:// 通过 Eloquent 查询删除... App\Order::where('price', '>', 100)->unsearchable(); // 你可以通过数据间的关系进行删除... $user->orders()->unsearchable(); // 你可以通过数据集合进行删除... $orders->unsearchable();
##Pause indexingYou may need to unsynchronize model data to search when performing a batch of Eloquent operations index. At this point you can use thewithoutSyncingToSearch
method to do this. This method accepts a callback that is executed immediately. All operations in this callback will not be synchronized to the model index:
App\Order::withoutSyncingToSearch(function () { // 执行模型操作... });
##Conditional search model instanceSometimes you may need a model to be searchable under certain conditions. For example, let's say you have an
App\Postmodel that can be in one of two states: "Draft" or "Published". You may only allow searches for "published" posts. To achieve this, you need to define a
saveshouldBeSearchable
method in your model:
Should only be used when operating via thepublic function shouldBeSearchable(){ return $this->isPublished(); }
method, query, or associated model
shouldBeSearchable
method. Using thesearchable
method directly will cause the model or collection's searchable results to override the results of theshouldBeSearchable
method:// 此处将遵循 "shouldBeSearchable" 结果... App\Order::where('price', '>', 100)->searchable(); $user->orders()->searchable();$order->save(); // 此处将覆盖 "shouldBeSearchable" 结果... $orders->searchable(); $order->searchable();
Search
You can use the
search
method to search for models. The search method accepts a string to search for the model. You also need to chain theget
method on the search query to query for a matching Eloquent model with a given search statement:$orders = App\Order::search('Star Trek')->get();
Scout search returns a collection of Eloquent models, so You can return results directly from a route or controller, and they will be automatically converted to JSON format:
use Illuminate\Http\Request; Route::get('/search', function (Request $request) { return App\Order::search($request->search)->get(); });
If you want to get the original results before they are returned to the Eloquent model, you should use
raw
Methods:$orders = App\Order::search('Star Trek')->raw();
Search queries are typically executed on the index specified by the model's
searchableAs
method. Of course, you can also specify a custom index that should be searched using thewithin
method:$orders = App\Order::search('Star Trek') ->within('tv_shows_popularity_desc') ->get();
Where statement
Allows you to add simple "where" statements to search queries. Currently, these statements only support basic numerical equality checks and are primarily intended for range search queries based on tenant IDs. Since the search index is not a relational database, the more advanced "where" statements are not currently supported:
$orders = App\Order::search('Star Trek')->where('user_id', 1)->get();
##PagingIn addition to retrieving a collection of models, you can also use thepaginate
method to paginate search results. This method returns a
Paginatorinstance just like traditional Eloquent query pagination:
$orders = App\Order::search('Star Trek')->paginate();
You can do this by passing the quantity as the first argument to thepaginate
method To specify how many models to retrieve for each page:
$orders = App\Order::search('Star Trek')->paginate(15);
After obtaining the retrieval results, you can use Blade to render paging links and display retrieval results, just like traditional Eloquent query paging:<div class="container"> @foreach ($orders as $order) {{ $order->price }} @endforeach </div> {{ $orders->links() }}
Soft deletionIf your indexed model is soft deleted and you need to search for soft deleted models, setconfig The value of the
soft_delete
option in /scout.phpconfiguration file is
true:
'soft_delete' => true,
When this configuration option istrue
, Scout does not remove soft-deleted models from the search index. Instead, it sets a hidden
__soft_deletedattribute in the index record. Then, when searching, you can use the
withTrashedor
onlyTrashedmethod to retrieve soft deleted records:
// 搜索结果包括已删除的记录... $orders = App\Order::withTrashed()->search('Star Trek')->get(); // 搜索结果只含已删除的记录... $orders = App\Order::onlyTrashed()->search('Star Trek')->get();
{Tip} To permanently delete the model, use
forceDelete
to delete, Scout will automatically remove the model from the search index.
Custom search engine
If you need to customize the search behavior of the engine, you can pass the callback as the second parameter to the
search
method. For example, you can use this callback to add geolocation data to the search request before passing it to Algolia:use Algolia\AlgoliaSearch\SearchIndex; App\Order::search('Star Trek', function (SearchIndex $algolia, string $query, array $options) { $options['body']['query']['bool']['filter']['geo_distance'] = [ 'distance' => '1000km', 'location' => ['lat' => 36, 'lon' => 111], ]; return $algolia->search($query, $options); })->get();
Custom engine
Writing engine
If the built-in Scout search engine cannot meet your needs, you can write a custom engine and register it with Scout. Your engine needs to inherit the
Laravel\Scout\Engines\Engine
abstract class. This abstract class contains seven methods that your customized engine must implement:use Laravel\Scout\Builder; abstract public function update($models); abstract public function delete($models); abstract public function search(Builder $builder); abstract public function paginate(Builder $builder, $perPage, $page); abstract public function mapIds($results); abstract public function map($results, $model); abstract public function getTotalCount($results); abstract public function flush($model);
in
It will be of great help to you to view the implementation of these methods in the Laravel\Scout\Engines\AlgoliaEngine
class. This class will provide you with a good starting point for learning how to implement these methods in a custom engine.Registering Engine
Once you have written your custom engine, you can register it with Scout using the
extend
method of Scout engine management. You only need to call theextend
method from theboot
method underAppServiceProvider
or any service provider used in the application. For example, if you have written aMySqlSearchEngine
, you can register it like this:use Laravel\Scout\EngineManager; /** * 启动任何的服务 * * @return void */ public function boot(){ resolve(EngineManager::class)->extend('mysql', function () { return new MySqlSearchEngine; }); }
After the engine is registered, you can go to
config/scout.php
Specify it as the default Scout in the configuration filedriver
:'driver' => 'mysql',
Generate macro command
If you want to customize the generator method, you can use the
macro
method under theLaravel\Scout\Builder
class. Usually, when defining "macros", you need to implement the service provider'sboot
method:<?php namespace App\Providers; use Laravel\Scout\Builder; use Illuminate\Support\ServiceProvider; use Illuminate\Support\Facades\Response; class ScoutMacroServiceProvider extends ServiceProvider{ /** * 注册应用的Scout 宏命令. * * @return void */ public function boot() { Builder::macro('count', function () { return $this->engine->getTotalCount( $this->engine()->search($this) ); }); } }
macro
The function accepts a name as the first parameter, and the second parameter is A closure function. When
calls theLaravel\Scout\Builder
macro command, this function is called.App\Order::search('Star Trek')->count();
This article was first published on the LearnKu.com website.
- Custom search engine