简介

Laravel Scout 为 Eloquent 模型全文搜索实现提供了简单的、基于驱动的解决方案。通过使用模型观察者,Scout 会自动同步更新模型记录的索引。

目前,Scout 通过 Algolia 驱动提供搜索功能,不过,编写自定义驱动很简单,你可以很轻松地通过自己的搜索实现来扩展 Scout。

注:Algolia 是一个托管式的全文搜索引擎,我们可以通过其提供的 API 在网站和移动应用中快速实现实时搜索功能。Algolia 提供的服务是收费的,不过我们可以使用其免费版本进行测试,免费版本支持 1 万条记录/10 万次操作。

安装

首先,我们通过 Composer 包管理器来安装 Scout:

composer require laravel/scout

安装完成后,需要通过 Artisan 命令 vendor:publish 发布 Scout 配置,该命令会发布配置文件 scout.php 到 config 目录:

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

最后,如果你想要某个模型支持 Scout 搜索,需要添加 Laravel\Scout\Searchable trait 到对应模型类,该 trait 会注册模型观察者来保持搜索驱动与模型记录数据的一致性:

<?php

namespace App;

use Laravel\Scout\Searchable;
use Illuminate\Database\Eloquent\Model; class Post extends Model
{
use Searchable;
}

队列

虽然不强制,但是在使用 Scout 之前强烈建议配置一个队列驱动。运行一个队列进程将允许 Scout 把所有同步模型信息到搜索索引的操作推送到队列中,从而为应用的 Web 接口提供更快的响应时间。

配置好队列驱动后,在配置文件 config/scout.php 中设置 queue 选项的值为true

'queue' => env('SCOUT_QUEUE', true),

驱动预备知识

Algolia

使用 Algolia 驱动的话,需要在配置文件 config/scout.php 中设置 Algolia 的 id 和 secret 信息(这些信息可以在注册登录 Algolia 之后在用户后台找到,分别对应 API Keys 下的 Application ID 和 Admin API Key)。配置好之后,还需要通过 Composer 包管理器安装 Algolia PHP SDK:

composer require algolia/algoliasearch-client-php

配置

配置模型索引

每个 Eloquent 模型都是通过给定的搜索“索引”进行同步,该索引包含了所有可搜索的模型记录,换句话说,你可以将索引看作是一个 MySQL 数据表。默认情况下,每个模型都会被持久化到与模型对应表名(通常是模型名称的复数形式)相匹配的索引中,不过,你可以通过重写模型中的 searchableAs 方法来覆盖这一默认设置:

<?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';
}
}

配置搜索数据

默认情况下,模型以完整的 toArray 格式持久化到搜索索引,如果你想要自定义被持久化到搜索索引的数据,可以重写模型上的 toSearchableArray 方法:

<?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(); // 自定义数组... return $array;
}
}

索引

批量导入

如果将 Scout 安装到了已存在的项目,可能该项目之前已经有了可以导入搜索驱动的数据库记录,Scout 提供了 Artisan 命令 import 用于导入所有已存在的数据到搜索索引:

php artisan scout:import "App\Post"

导入成功后,我们在 Algolia 后台就可以看到导入成功的索引数据:

添加记录

添加 Laravel\Scout\Searchable trait 到模型之后,剩下需要做的就是保存模型实例,然后该实例会自动被添加到模型索引,如果你配置了 Scout 使用队列,该操作会被推送到队列在后台执行:

$post = new App\Post;

$post->title = 'Scout是什么';
$post->content = 'Scout是Laravel官方提供的全文搜索解决方案';
$post->user_id = 1; $post->save();

模型数据保存之后,也会通过 Scout 同步到 Algolia:

通过查询添加

如果你想要通过 Eloquent 查询添加模型集合到搜索索引,可以在 Eloquent 查询之后追加 searchable 方法调用。searchable 方法会分组块进行查询并将结果添加到搜索索引。再次强调,如果你配置了 Scout 使用队列,所有的组块查询会被推送到队列在后台进行:

// 通过 Eloquent 查询添加...
App\Post::where('user_id', '>', 10)->searchable(); // 还可以通过关联关系添加记录...
$user->posts()->searchable(); // 还可以通过集合添加记录...
$posts->searchable();

searchable 方法会进行“upsert”操作,换句话说,如果模型记录已经存在于索引,则会被更新,如果不存在,才会被添加。

更新记录

要更新支持搜索的模型,只需更新模型实例的属性并保存模型到数据库。Scout 会自动持久化更新到搜索索引:

$post = App\Post::find(2);

$post->title = '学院君是谁';
$post->content = '学院君创建了Laravel学院,故而得名'; $post->save();

去 Algolia 查看索引数据,已更新:

还可以使用模型查询提供的 searchable 方法更新模型集合,如果模型在搜索索引中不存在,则会被创建:

// 通过 Eloquent 查询更新...
App\Post::where('user_id', '>', 10)->searchable(); // 还可以通过关联关系更新...
$user->posts()->searchable(); // 还可以通过集合更新...
$posts->searchable();

删除记录

要从索引中删除记录,只需从数据库中删除对应记录即可,这种删除方式甚至兼容软删除模型:

$post = App\Post::find(1);

$post->delete();

如果你在删除记录前不想获取模型,可以使用模型查询实例或集合上的 unsearchable 方法:

// 通过 Eloquent 查询移除...
App\Post::where('user_id', '>', 10)->unsearchable(); // 还可以通过关联关系移除...
$user->posts()->unsearchable(); // 还可以通过集合移除...
$posts->unsearchable();

暂停索引

有时候你需要在不同步模型数据到搜索索引的情况下执行批量的 Eloquent 操作,可以通过 withoutSyncingToSearch方法来实现。该方法接收一个立即被执行的回调,该回调中出现的所有模型操作都不会同步到搜索索引:

App\Post::withoutSyncingToSearch(function () {
// Perform model actions...
});

搜索

你可以通过 search 方法来搜索一个模型,该方法接收一个用于搜索模型的字符串,然后你还需要在这个搜索查询上调用一个 get 方法来获取与给定搜索查询相匹配的 Eloquent 模型:

$posts = App\Post::search('学院')->get();

由于 Scout 搜索返回的是 Eloquent 模型集合,你甚至可以直接从路由或控制器中返回结果,它们将会被自动转换为 JSON 格式:

use Illuminate\Http\Request;

Route::get('/search', function (Request $request) {
return App\Post::search($request->search)->get();
});

搜索「学院」的话,返回两条搜索结果:

如果你想要获取原生搜索结果而不是转化后的 Eloquent 模型,可以使用 raw 方法:

$posts = App\Post::search('学院')->raw();

返回数据如下:

搜索查询使用模型类的 searchAs 方法指定的索引进行查询。不过,你也可以使用 within 方法指定一个自定义的索引进行搜索:

$posts = App\Post::search('学院')
->within('users_index')
->get();

where 子句

Scout 允许你添加简单的 where 子句到搜索查询,目前,这些子句仅支持简单的数值相等检查,由于搜索索引不是关系型数据库,更多高级的 where 子句暂不支持:

$posts = App\Post::search('学院')->where('user_id', 1)->get();

分页

除了获取模型集合之外,还可以使用 paginate 方法对搜索结果进行分页,该方法返回一个 Paginator 实例 —— 就像你对传统 Eloquent 查询进行分页一样:

$posts = App\Post::search('学院')->paginate();

返回结果如下:

你可以通过传入数量作为 paginate 方法的第一个参数来指定每页显示多少个模型:

$posts = App\Post::search('学院')->paginate(15);

获取结果之后,可以使用 Blade 显示结果并渲染分页链接,就像对传统 Eloquent 查询进行分页时一样:

<div class="container">
@foreach ($orders as $order)
{{ $order->price }}
@endforeach
</div> {{ $orders->links() }}

自定义引擎

编写引擎

如果某个内置的 Scout 搜索引擎不满足你的需求,可以编写自定义的引擎并将其注册到 Scout,自定义的引擎需要继承自抽象类 Laravel\Scout\Engines\Engine,该抽象类包含了 7 个自定义引擎必须实现的方法:

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);

这些方法的实现可以参考 Laravel\Scout\Engines\AlgoliaEngine 类,这个类为我们学习如何在自定义引擎中实现这些方法提供了最佳范本。

注册引擎

编写好自定义引擎之后,可以通过 Scout 引擎管理器提供的 extend 方法将其注册到 Scout。你需要在 AppServiceProvider(或者其他服务提供者)的 boot 方法中调用这个 extend 方法。例如,如果你编写了 MySqlSearchEngine,可以这样注册:

use Laravel\Scout\EngineManager;

/**
* 启动任意应用服务.
*
* @return void
*/
public function boot()
{
resolve(EngineManager::class)->extend('mysql', function () {
return new MySqlSearchEngine;
});
}

引擎被注册之后,可以在配置文件 config/scout.php 中将其设置为 Scout 默认的驱动:

'driver' => env('SCOUT_DRIVER', 'mysql'),

[ Laravel 5.5 文档 ] 官方扩展包 —— 全文搜索解决方案:Laravel Scout的更多相关文章

  1. Laravel 5.5 文档 ] 快速入门 —— 安装配置篇

    服务器要求 Laravel 框架对PHP版本和扩展有一定要求,不过这些要求 Laravel Homestead 都已经满足了,不过如果你没有使用 Homestead 的话(那真是一件很遗憾的事情),有 ...

  2. MFC单文档自定义扩展名及添加图标报Assertion错误

    忽然无聊的想给自己写的程序保存的文件使用自己的名字简写作为后缀,于是有了下文. IDR_MAINFRAME格式介绍 IDR_MAINFRAME字符串资源中包含7个子串,分别以/n结束,即如下格式: & ...

  3. [ Laravel 5.5 文档 ] 处理用户请求 —— HTTP 请求的过滤器:中间件

    [ Laravel 5.5 文档 ] 处理用户请求 —— HTTP 请求的过滤器:中间件 http://laravelacademy.org/post/7812.html 简介 中间件为过滤进入应用的 ...

  4. JAVA连接Excel最好用的开源项目EasyExcel,官方使用文档及.jar包下载

    EasyExcel是一个基于Java的简单.省内存的读写Excel的开源项目.在尽可能节约内存的情况下支持读写百M的Excel. github地址:https://github.com/alibaba ...

  5. [ Laravel 5.5 文档 ] 快速入门 —— 目录结构篇

    简介 Laravel 默认的目录结构试图为不管是大型应用还是小型应用提供一个良好的起点.当然,你也可以按照自己的喜好重新组织应用的目录结构,因为 Laravel 对于指定类在何处被加载没有任何限制 — ...

  6. [ Laravel 5.5 文档 ] 底层原理 —— 一次 Laravel 请求的生命周期

     Posted on 2018年3月5日 by  学院君 简介 当我们使用现实世界中的任何工具时,如果理解了该工具的工作原理,那么用起来就会得心应手,应用开发也是如此.当你理解了开发工具如何工作,用起 ...

  7. Python读取word文档(python-docx包)

    最近想统计word文档中的一些信息,人工统计的话...三天三夜吧 python 不愧是万能语言,发现有一个包叫做 docx,非常好用,具体查看官方文档:https://python-docx.read ...

  8. jdk1.6文档官方下载资源

    JDK1.6官方下载_JDK6官方下载地址:http://www.java.net/download/jdk6/6u10/promoted/b32/binaries/jdk-6u10-rc2-bin- ...

  9. Dapper的封装、二次封装、官方扩展包封装,以及ADO.NET原生封装

    前几天偶然看到了dapper,由于以前没有用过,只用过ef core,稍微看了一下,然后写了一些简单的可复用的封装. Dapper的用法比较接近ADO.NET所以性能也是比较快.所以我们先来看看使用A ...

随机推荐

  1. Reveal逆向工程:分析任意iOS应用的UI界面

    在iOS逆向工程中,Reveal扮演着重要角色,一般情况下,Reveal在iOS开发过程中可以分析UI界面的状态,同样也可以应用于分析其他任意的App.特别是对于初学者来说,去了解其他优秀App的界面 ...

  2. spring boot 集成 druid

    写在前面 因为在用到spring boot + mybatis的项目时候,经常发生访问接口卡,服务器项目用了几天就很卡的甚至不能访问的情况,而我们的项目和数据库都是好了,考虑到可能是数据库连接的问题, ...

  3. JavaMail发送和接收邮件API(详解)

    一.JavaMail概述: JavaMail是由Sun定义的一套收发电子邮件的API,不同的厂商可以提供自己的实现类.但它并没有包含在JDK中,而是作为JavaEE的一部分. 厂商所提供的JavaMa ...

  4. Tesseract ocr 3.02学习记录一

    光学字符识别(OCR,Optical Character Recognition)是指对文本资料进行扫描,然后对图像文件进行分析处理,获取文字及版面信息的过程.OCR技术非常专业,一般多是印刷.打印行 ...

  5. DELPHI - How to use opendialog1 for choosing a folder? TOpenDialog, TFileOpenDialog

    DELPHI - How to use opendialog1 for choosing a folder? On Vista and up you can show a more modern lo ...

  6. C++ STL set::find的用法

      参考: http://blog.csdn.net/lihao21/article/details/6302196 /* class for function predicate * - opera ...

  7. Google 镜像站搜集

    在特殊的地方和特殊的时间,流畅顺利的打开一个网站也变得如此艰难. 2016.01.16 更新.本站订阅更新功能已上线,欢迎订阅! 以下是直接使用谷歌的方法,如需***戳这里(VPN | Shadows ...

  8. 【iOS开发-91】GCD的同步异步串行并行、NSOperation和NSOperationQueue一级用dispatch_once实现单例

    (1)GCD实现的同步异步.串行并行. --同步sync应用场景:用户登录,利用堵塞 --串行异步应用场景:下载等耗时间的任务 /** * 由于是异步.所以开通了子线程.可是由于是串行队列,所以仅仅须 ...

  9. Lombok使用详解(转)

    本文转自https://blog.csdn.net/u010695794/article/details/70441432 2017年04月22日 15:17:00 阅读数:10394 Lombok使 ...

  10. C语言控制结构

    C语言流程控制 一.流程控制结构 (1)顺序结构:按书写顺序执行每一条语句. (2)选择结构:对给定的条件进行判断,根据判断结果决定执行哪一段代码. (3)循环结构:在给定条件成立的情况下,反复执行某 ...