在 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 分詞, 好吧, 我認可我找不到了, 好吧, 我認可我實在不想找了, 閃~~~~

相關文章
相關標籤/搜索