在 Laravel 项目中使用 Elasticsearch 作引擎,scout 全文搜索(小白出品, 绝对白话)

项目中须要搜索, 因此从零开始学习你们都在用的搜索神器 elasiticsearch. 刚开始 google 的时候, 搜到好多经验贴和视频(中文的, 英文的), 可是因为是第一次接触, 一点概念都没有, 你们介绍的方法又有点不尽相同, 因此有点懵逼, 最后通过层层筛选, 终于找到组织 Elasticsearch: 权威指南. 这是中文翻译版的, 我目前以为还能够哈, 语言比较朴实. php

而后呢, 由于我本身在从下载安装这些基本的操做过程当中都走了不少的弯路, 因此我把最实用的干货仍是总结一下, 方便下次直接上手, 最起码能够先跑起来哈. 至于对于 elasticsearch 的深刻理解, 你们仍是看<<权威指南>>吧.java

第一步: 下载安装 ES

我真的是找到了各类版本的下载安装命令, 有些命令根本跑不通, 让我非常头大, 固然, 我本身是 macos 系统的, 因此个人一切安装步骤也都只是保证绝对适用于 macos:mysql

  1. 到官网下载压缩包 根据本身的系统选择哈: 
  2. 把压缩包解压, 解压后的文件我暂且放在我如今作的项目里了, 而后在终端进入这个文件.(这里说明一下, 只要进入你刚刚下载的那个文件夹就好了, 版本号不用 copy 个人, 由于有可能已经更新了.)
cd elasticsearch-6.6.1 

以后, 执行下面的命令启动服务(若是你想把 Elasticsearch 做为一个守护进程在后台运行,那么能够在后面添加参数 -d):laravel

./bin/elasticsearch 

经过以上两步, 应该说 elasticsearch 就已经开始为你的站点服务了. 为了 double check 是否启动成功,能够打开另外一个终端,执行如下操做:git

curl 'http://localhost:9200/?pretty' 

若是你能获得相似下面的结果, 就意味着你如今已经启动并运行一个 Elasticsearch 节点了:github

{ "name" : "27qRw7J", "cluster_name" : "elasticsearch", "cluster_uuid" : "RFuFAGLaRVqtlJOyn-hFWA", "version" : { "number" : "6.6.1", "build_flavor" : "default", "build_type" : "tar", "build_hash" : "1fd8f69", "build_date" : "2019-02-13T17:10:04.160291Z", "build_snapshot" : false, "lucene_version" : "7.6.0", "minimum_wire_compatibility_version" : "5.6.0", "minimum_index_compatibility_version" : "5.0.0" }, "tagline" : "You Know, for Search" } 

第二步: 安装中文分词插件 IK

Elasticsearch原装分词器会简单地拆分每一个汉字,没有根据词库来分词,这样的后果就是搜索结果极可能不是你想要的。这里推荐使用elasticsearch-analysis-ik,支持自定义词库。 文档推荐了两种下载安装方式, 两种我都试了, 可是第二种一直报错, google 了一下, 不少人都有这个问题, 貌似是不支持了....额. 因此就推荐你们直接用第一种方式吧, 就是直接下载文件, 解压以后放到 your-es-root/plugins/ik 文件夹里. 这种方法理论上是没啥问题的, 可是我依然踩了一个很丢人的坑, 估计大部分都不会犯这个错误吧, 就是我是手动解压的, 解压以后生成了一个文件夹, 我就把这个文件夹直接放到 ik 文件夹里了, 而后重启 es 的时候就一直报错. 因此应该是把解压后的文件夹里的全部文件都直接放进 ik 文件夹里~~~~~ web

而后重启 es 就行了. sql

第三步: 安装 scout

这个是 laravel 官方推出的全文搜索包, 是针对Eloquent 模型开发的一个简单的,基于驱动的全文检索系统. 若是你跟我同样也是第一次接触, 确定也会以为这句话有点晦涩难懂吧, 不要紧, 我开始也是这样的. 经过把整个过程理顺以后, 我如今的白话理解就是, elasticsearch 就比如是一个数据库, 只不过跟 mysql 的存储方式不一样. 这个数据库虽然使用 java 写的, 可是它也支持不少不少其余语言, 你们均可以以 RESTful API 的形式跟它交互(无非就是存储数据啦). 也就是说, 针对不一样的请求它都有相应的接口暴露出来, 那咱们能够直接使用这些接口的, 就好像你直接写 sql 语句查数据库同样, 可是 贴心的 laravel 以为原生请求太不优雅了, 因此它封装了一个包 scout. 好了, 但愿我这翻废话能对你理清关系有所帮助. 下面开始安装了:数据库

先安装 scout 的 es 驱动 tamayo/laravel-scout-elastic:macos

composer require tamayo/laravel-scout-elastic 

, 这里要说明一下, 目前这个包的最新版本是 4.0.0, 而这个版本只支持 scout ^5.0 的版本, 因此尽管此时 scout 的最新版本已经到了 7.0, 我在安装 scout 的时候仍是要指明 5.0 的版本:

composer require laravel/scout ^5.0 

经过 laravel/scout 的官方文档能够看到, 它是默认只支持使用 Algolia 驱动, 可是咱们的目标是用 es 作驱动, 因此要改一下 config/scout.php 的配置.

找到下面这行代码:

‘driver’ => env(‘SCOUT_DRIVER’, ‘algolia’), 

把它改成:

‘driver’ => env(‘SCOUT_DRIVER’, ‘elasticsearch’), 

以后, 在最下面添加以下代码:

elasticsearch’ => [ ‘index’ => env(‘ELASTICSEARCH_INDEX’, ‘laravel’), ‘config’ => [ ‘hosts’ => [ env(‘ELASTICSEARCH_HOST’, ‘localhost’), ], ], ], 

而后在 .env 文件中添加:

ELASTICSEARCH_INDEX=scout ELASTICSEARCH_HOST=http://localhost:9200 

以上, 算是把工具都准备齐了, 下面就是开干了.

可是, 在开始以前, 还想再说几句废话, 就是建议你们仍是看一下  Elasticsearch: 权威指南, 虽然我也尚未彻底看完, 可是最起码在我对 es 存储数据的结构, 在脑海里是有大概了解的, 也就是对像 "索引", "文档" 这些概念都知道是表明什么的, 这些在权威指南里都解释得很白话的, 我是以为在我这篇文章里, 很难去解释的那么清楚...... 因此, 若是你不是那么赶时间的话, 仍是建议先去大概过一遍. 若是实在没时间, 就跟着下面的步骤作, 也是 OK 嗒.

接下来, 以我本身的项目为例, 我有一个 Post 表须要作全文索引, 个人表是已经建好的, 里面也已经有 40条测试数据, 如今我就要把这个表索引到 es 中:

php artisan scout:import "App\Post" 

会获得下面的反馈, 证实导入成功了:

Imported [App\Post] models up to ID: 40 All [App\Post] records have been imported. 

下面测试一下搜索功能, 打开 tinker:

php artisan tinker

执行如下命令:

App\Post::search('Blake Swaniawski')->get(); 

若是一切正常的话, 应该会返回一堆 JSON 字符串(注意: 这里换成你本身的 model)

经过简单的测试之后, 咱们就能够应用到项目中啦.
新建一个 searchController:

php artisan make:controller SearchController 

打开这个新建的 controller 文件, 添加以下方法:

public function search(Request $request){ if($request->has('search')){ $posts = Post::search($request->input('search'))->get(); } return view('web.search.results', compact('posts')); } 

打开 web.php 文件, 添加路由:

Route::get('/SearchQuery', 'SearchController@search'); 

以后打开带搜索框的 blade 模板(个人就是在 layout 里, 我就只截取搜索框的代码了). 这里的 class 你们均可以忽略, 主要就是关注配置表单提交的信息, 还有就是 input 框的 name 必定要是 "search":

<form class="form-inline my-2 my-lg-0" id="elasticScout" action="/SearchQuery" method="get"> <input class="form-control mr-sm-2 form-control-sm" type="search" placeholder="搜索" aria-label="Search" name="search"> <button class="btn btn-outline-secondary btn-sm my-2 my-sm-0" type="submit">搜索</button> </form> 

最后再根据 searchController 里返回的 view, 建一个展现查询结果的 result 页面, 并在页面中把 查询结果循环输出:

@if(!empty($posts)) @foreach($posts as $post) <h1>{{ $post->content }} </h1> @endforeach @endif 

终于.....写完了.....
我真的弯弯曲曲走了差很少两天, follow 了好几位前辈的经验, 东拼西凑, 最终总结了一条最适合我本身的路(捂脸笑). 把我参考的前辈的文章也分享一下, just in case for u ~~~~~

这是我看到的最后一篇, 或许是因为有了前面一天的积累, 看到这篇的时候, 我有种豁然开朗的感受, 因此我后面的主要思路也是参考它的, 以后稍微填了各别小坑:
Basic Search Functionality with ElasticSearch & Laravel Scout

我抄袭了这位前辈的题目, 由于我以为我想不到更好的(嘻嘻), 可是恕我太白, 我没法彻底 follow 他的思路:
Laravel5.5 使用 Elasticsearch 作引擎,scout 全文搜索

还有一篇来自 laravel-china 的, 我从那里学到了要用 ik 分词, 好吧, 我认可我找不到了, 好吧, 我认可我实在不想找了, 闪~~~~

相关文章
相关标签/搜索