Laravel5.3已经发布了,这次版本多了一个官方工具包:scout。这个包的作用就是帮助大家更好的将全文检索工具和项目更好的结合,让开发者使用起来更方便。但是我发现了一个问题:Laravel官方文档对于scout的使用说明并没有那么详细,只讲了如何将检索工具“Algolia”(法国一家公司提供的检索PaaS服务)和Laravel结合的使用方式,而没有讲使用ElasticSearch的方式,但是其实scout已经完成对ElasticSearch的结合了(详细请翻阅代码);我感觉这样略微不妥,因为ElasticSearch的使用要比“Algolia”广泛的多,于是乎,便有了此文。
下面我们一步一步来:
第一,准备工作,install;
运行
composer require laravel/scout
把依赖下下来之后,往项目目录config/app.php 中加入这个class
Laravel\Scout\ScoutServiceProvider::class,
之后运行如下命令,
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
这条命令会让配置文件夹 中多了一配置文件 scout.php最后,你想让哪个Model实现全文搜索,你就让哪个Model继承 Laravel\Scout\Searchable这个trait 就好了
(以上内容都是文档的重复,请仔细阅读文档)
第二,开始配置scout的配置文件等内容。
我们要利用elasticsearch就首先需要下载elasticsearch的php client,来用于Elasticsearch的 engine
composer require elasticsearch/elasticsearch
然后打开 config/scout.php 这个文件,
这里每一个配置信息都有详细的说明,都很好理解,假如咱们想用elasticsearch,那么algolia的东西咱们可以不必care,重点关注‘elasticsearch’和‘driver’两个选项,queue如果随自己选择,想加就加,不加就写false。
‘elasticsearch’的配置可以根据自己项目的需要填写,例如我们的所需的elasticsearch的index是‘apache’,hosts地址是“192.168.99.100:9200”就可以按照如下设置:
/* |-------------------------------------------------------------------------- | Elasticsearch Configuration |-------------------------------------------------------------------------- | | Here you may configure your settings for Elasticsearch, which is a | distributed, open source search and analytics engine. Feel free | to add as many Elasticsearch servers as required by your app. | */ 'elasticsearch' => [ 'index' => env('ELASTICSEARCH_INDEX', 'Apache'), 'config' => [ 'hosts' => [ env('ELASTICSEARCH_HOST', "192.168.99.100:9200") ], ], ],
再就是写Driver了,我们来看看官方提供了哪些driver
/* |-------------------------------------------------------------------------- | Default Search Engine |-------------------------------------------------------------------------- | | This option controls the default search connection that gets used while | using Laravel Scout. This connection is used when syncing all models | to the search service. You should adjust this based on your needs. | | Supported: "algolia", "null" | */
一共俩,一个是aloglia,另外一个是null,前者很好理解,就是algolia相关的,那么填写null会出现什么呢?其实null是为项目中暂时不需要搜索功能的项目而制作的,假如你的项目中没有任何搜索引擎,那么就填null,否则在运行scout相关的指令的时候项目会报错。其实,通过看源码可以发现,laravel-scout还帮我们实现了另外一种搜索引擎的方式——elasticsearch,但是不知为什么,目前的版本(laravel 5.3)没有对此方式做一些介绍,希望后续的版本会做补充。
在使用elasticsearch的时候,driver应该这么填写:
'driver' => env('SCOUT_DRIVER', 'elasticsearch'),
这样,配置信息就基本搞定了。第三,将数据库数据“灌入”搜索引擎中。
确保让“XXX\XXX\User”继承
Laravel\Scout\Searchable
这个trait运行指令:php artisan scout:import “XXX\XXX\User” (这里的类名要写全称,namespace + 类名);
然后,就可以搜索了,搜索方式是:
1、search方法;每个表每个字段匹配:假如我写
App\User::search('AAA')->get();
,那么user表中所有字段中包含“AAA”字段的内容就都会查出来。2、where语句,每次search之后,都可以跟where语句,加以“过滤” 例如:
App\User::search('AAA')->where('gender', 1)->get()
这样就可以查出user表中所有包含“刘刚”字段的、并且性别为1 的内容
3、pagination方法;
App\User::search('AAA')->paginate(15);
这样,就会返回15条数据。
自定义引擎
有些时候,利用项目自带的搜索引擎的搜索方式有很大的局限性,当前版本(laravel 5.3)的scout使用的elasticsearch仅仅使用了其中很小的部分,elasticsearch的强大功能不能很好的利用,例如:
1、scout默认的elasticsearch 录入的数据结构都是数据库中的数据结构,不能使用elasticsearch的自定义的数据结构。
2、scout默认的elasticsearch不支持中文分词,无法使用用户自己想要定制的分词结构。
3、scout默认的elasticsearch搜索方式太单一,elasticsearch的搜索方式非常的多并且精细而scout默认的方式只能提供布尔查询:
查询结构为:
(1)、不加where语句:
[index] => apache [type] => users [body] => [ [query] => [ [bool] => [ [filter] => [ [query_string] =>[ [query] => *李勤* ] ] ] ] ] [size] => 10000 ]
(2)、加上where语句:
[index] => apache [type] => users [body] => [ [query] => [ [bool] =>[ [filter] => [ [query_string] => [ [query] => *王* ] ] [must] =>[ [match] =>[ [role] => 2 ] ] ] ] ] [size] => 10000 ]
这种查询结构显然不能应对千变万化的需求。
应对这个问题,我们采用scout提供的自定义搜索的功能,要使用此功能也非常简单:
第一,继承并实现Laravel\Scout\Engines\Engine这个抽象类,然后重写必须的抽象方法:
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 map($results, $model);
如果你看过源码,你并不感到奇怪,是的,scout默认的两个搜索引擎aligo 和 elasticsearch 也都是这么实现的。第二,在AppServiceProvider 填上注册内容:
use Laravel\Scout\EngineManager; /** * Bootstrap any application services. * * @return void */ public function boot() { resolve(EngineManager::class)->extend('mysql', function () { return new MySqlSearchEngine; }); }
第三,配置scout文件:
'driver' => 'mysql',
然后,你就可以正常运行啦!
scout源码运行流程图及我想到的更改图
我的customer 引擎继承了源码中的ElasticSearchEngine,然后做了部分修改