Laravel Scout 包在 Elasticsearch 中的應用

軒脈刃發表於2017-04-05

laravel的Scout包是針對自身的Eloquent模型開發的基於驅動的全文檢索引擎。意思就是我們可以像使用ORM一樣使用檢索功能。不管你用的是什麼搜尋引擎,scout包給你封裝好了幾個方法

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

你只需要建立一個引擎(比如es引擎)就可以使用orm來操作search了。

可惜laravel的scout包只提供了Algolia的驅動。我個人很喜歡的es並沒有提供驅動。好在網上有人分享了驅動,比如 https://github.com/ErickTamayo/laravel-sco...

看裡面的程式碼,其實很簡單,兩個類,一個類ElasticsearchEngine用於實現Scout定義的幾個方法,一個類ElasticsearchProvider用於做服務註冊。我們使用composer require就能用好這個類了。這裡就不說了。

說說laravel的scout包在es裡面是怎麼儲存的。首先,在配置檔案裡面elasticsearch建立一個index

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

    ...    
    'elasticsearch' => [
        'index' => env('ELASTICSEARCH_INDEX', 'laravel'),
        'hosts' => [            
            env('ELASTICSEARCH_HOST', 'http://localhost'),
            ],
        ],
    ...

然後每個對應的model都是不同的type。這個type的名字是在model裡面定義的。

class Post extends Model
use Laravel\Scout\Searchable;

class Post extends Model
{
    use Searchable;

    protected $table = "posts";

    /*
     * 搜尋的type
     */
    public function searchableAs()
    {
        return 'posts_index';
    }

    public function toSearchableArray()
    {
        return [
            'title' => $this->title,
            'content' => $this->content,
        ];
    }

所以它裡面每個條目實際上是這麼一個結構:

1 scout會很聰明把表的主鍵作為es的_id

這個真是非常贊,不需要儲存一個id,做_id和id的關聯了

2 scout在model做增刪改查的時候會自動更新索引

這個也是我們最需要的,索引資料和資料庫資料的同步使用程式碼進行保證了。當然,用程式碼保證可能並不是什麼很好的方法,但是對於小型的網站來說,這個無疑增加了便捷性。

3 scout的建立索引方法是一個網站統一一個index, 不同的model使用不同的type

這種一個index多type的形式是否適用你的專案呢?不一定,如果你的model各不相同,可能多個index更好點。關於index和type的選擇,https://www.elastic.co/blog/index-vs-type 可以參考這篇。所以這種方式可能更適合的是儲存到es的都是文字的搜尋。

4 search函式里面不能指定搜尋欄位

比如我的Post索引存入了title和content。那麼我使用Post::search("china")的時候,搜尋出來的結果就是title和content中包含有china的。如果我想搜尋content中包含有"china"的,沒辦法,scout做不到,只能自己做擴充套件了。

5 分頁指定了查詢的欄位名必須是query

這個意思是在搜尋介面,你上交上來的查詢介面必須是query=xx,形如http://127.0.0.1:8000/posts/search?query=china
看了原始碼發現這個query欄位是由Scout/Builder寫死在程式碼裡面的...這個估計很多人用到這個分頁的時候會踩進去

6 搜尋的query強制使用萬用字元

這個是laravel-scout-elasticsearch的問題了,它在query的時候強制在搜尋的前後使用上了萬用字元*,這個在標準分詞器中文搜尋的時候會出現問題,會變成一個詞,具體問題可以看這個帖子:http://elasticsearch.cn/question/228

所以如果要使用標準分詞器,需要把query的前後兩個*都去掉,具體程式碼在vendor/tamayo/laravel-scout-elastic/src/ElasticsearchEngine.php中。

scout還是主要偏向於統一搜尋介面,如果你的網站很小,並且搜尋只是作為文字搜尋的話,那麼用這個是非常合適的,但是如果你的搜尋功能佔你的網站大部分功能的話,那麼我建議我們可以使用scout做搜尋和資料庫的同步,其他的搜尋請求,我們使用elasticsearch/elasticsearch自己寫比較好。

本作品採用《CC 協議》,轉載必須註明作者和本文連結

相關文章