基于迅搜(xunsearch) + Laravel Scout 实现 Laravel 学院全文搜索功能(支持多模型搜索)


概述

Laravel Scout 为 Eloquent 模型全文搜索实现提供了简单的、基于驱动的解决方案。通过使用模型观察者,Scout 会自动同步更新模型记录的索引,非常方便,易于上手,学院的文章搜索功能正好可以通过它来实现。

Laravel Scout 基于模型 + 底层搜索驱动扩展包来实现模型的全文搜索,目前,Scout 默认通过 Algolia 驱动提供搜索功能,不过,编写自定义驱动很简单,我们可以很轻松地通过自己的搜索实现来扩展 Scout。Algolia 毕竟是收费 API,而且是国外的服务,国内访问速度和可用性上不能保证,所以很自然被略过,接下来的选择就是自己搭建搜索引擎了,中文搜索有多种解决方案,比如轻量级的迅搜(xunsearch)、coreseek(sphinx变种,支持中文搜索),适用于中小型应用,还有适用于大型应用的 Elasticsearch

对于学院的规模来说使用迅搜就够了,简单易上手,只需少许步骤就可以快速搭建其自己的搜索引擎,而且它们的客户中就有国内著名的编程社区 segmentfault,有这样的背书也可以让我们放心使用。

安装迅搜服务端

在服务器上安装迅搜很简单,只需以下几步即可:

安装完成后,通过以下命令启动:

以上命令默认在本地回环地址(127.0.0.1)8383/8384上监听服务,如果你有多台机器需要访问迅搜服务端,需要通过以下命令启动:

以上过程没有报错,就意味着迅搜已经正常启动了。

如果通过 Docker 启动迅搜服务的话,对应 Dockerfile 如下:

安装相关 PHP 扩展包

首先通过 Composer 安装 xunsearch 扩展包:

安装完迅搜扩展包后,在 Laravel 中使用 Scout 也需要安装对应扩展包:

将配置文件 scout.php 发布到 config 目录下:

scout.php 中新增 xunsearch 相关配置:

接下来需要修改 .env 中的相关配置:

注意到我们将 SCOUT_DRIVER 改成了 xunsearchXUNSEARCH_HOST 必须与你安装迅搜所在的服务器IP一致,最后我们将索引构建设置为通过队列异步执行,学院君通过 Laravel Horizon 实现队列系统,关于这方面的内容请移步对应文档查看,这里不再单独介绍。

学院暂时只支持文章搜索,所以需要为对应模型中添加如下代码以支持自动更新索引和搜索:

索引配置文件

由于我们只是对学院文章进行搜索,所以只要为其定义相应的索引配置文件即可,在 config 目录下创建xs_article.ini

索引哪些字段由你自己决定,这里只是个参考,关于字段明细介绍,请参考迅搜官方文档,这里不在赘述,要想了解迅搜搜索引擎工作流程和原理,请务必先仔细阅读一遍迅搜官方文档

编写迅搜 Scout 扩展类

要实现基于迅搜驱动的搜索功能,还需要为其编写 Scout 扩展 XunSearchEnginge

以上代码包含搜索、索引构建、删除、分页等所有功能,接下来需要做的就是将其绑定到 Scout 扩展中,我们可以通过在 AppServiceProviderboot 方法中添加以下代码来实现:

演示搜索功能

完成以上所有工作后,就可以在更新/新增文章模型后对其进行搜索了,更新/新增模型后可以在 Horizon 后台看到队列中的索引更新/新增记录:

索引更新队列

队列任务执行完成后,就可以通过搜索框进行搜索了,执行搜索的代码实现也很简单:

以上是一个分页搜索,比如我们搜索「Laravel学院」,显示结果如下:

Laravel学院搜索结果页面

多模型搜索支持

=============== 2018.11.04 更新 ===============

上述实现只能对文章进行搜索,并且将索引字段硬编码到引擎类 XunSearchEngine 中,如果后续需要对更多模型进行搜索,比如问答模块要支持搜索功能,现在的实现就不能满足了,比较偷懒的实现是为每个索引生成不同的引擎实例,然后将 XunSearchEngine 类的 update 方法中索引字段同步部分迁移出去。下面给出一个简单的实现示例:

因为学院主要还是文章搜索,所以保留文章搜索引擎 xunsearch 作为主搜索引擎,即默认引擎,所以注册该引擎的地方保持不变,我们在 Article 模型类中定义一个新方法用于将模型字段数据同步到搜索索引字段:

然后将 XunSearchEngineupdate 方法中同步模型数据到索引部分代码修改如下:

这样就将这部门硬编码重构出去了,接下来,要实现问答模块搜索,需要在其模型类 Discussion 中使用 Searchable Trait:

然后在这个模型类中通过重写 Searchable 中的 searchableUsing 方法来定义该模型搜索使用的搜索引擎实例:

我们为 Discussion 模型创建了新的索引配置文件 xs_discussion.ini,具体配置参考 xs_article.ini 定义即可,这里不再赘述,然后返回新的引擎实例用于问答模型搜索,当然还要在模型类中定义模型字段同步方法:

这样我们就完成了基于迅搜 + Laravel Scout 的多模型搜索功能的实现,在终端运行如下命令初始化问答模型索引数据:

这样就可以在应用中通过 Discussion::search('问题描述')->paginate($pageSize, 'page', $page) 进行问答模型的搜索了。


<< 上一篇: 由浅入深:基于 Laravel Broadcast 实现 WebSocket C/S 实时通信

>> 下一篇: 基于七牛云 PHP SDK + Laravel 文件存储实现 Laravel 学院静态资源云存储及 CDN 加速