laravel Scout包在elasticsearch中的應用


laravel Scout包在elasticsearch中的應用

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-scout-elastic

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

scout包在es中的存儲

說說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自己寫比較好。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM