之前在自己的 Laravel 6.x 測試專案中使用 Elasticsearch 做全文搜尋,發現 Elasticsearch 在中文搜尋部分有問題,請孤狗大神找了相當多資料,絕大部份中文資料都停留在 Laravel 6.x 以下,試驗了 ICU 及 IK 中文分詞插件也不盡理想,可能是我功力太差,不知道如何設定,只好放棄使用 Elasticsearch 了,改用輕量的 TNTSearch

前置準備

TNTSearch 不像 Elasticsearch 那樣複雜,只需安裝 Sqlite3 當作資料庫,XAMMP 需修改 php.ini 將 sqlite3 啟用,並下載 Windows 版本的 dll 放到 XAMPP 的 Apache/bin 目錄中,重新啟動 Apache 即可。

# 將註解拿掉
extension=pdo_sqlite
extension=sqlite3

安裝 Laravel Scoutvanry/laravel-scout-tntsearch 套件

vanry/laravel-scout-tntsearch 這個套件會自動將 TNTSearch 驅動一併安裝。

composer require vanry/laravel-scout-tntsearch
# Scout 設定檔
php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
# Tntsearch 設定檔
php artisan vendor:publish --provider="Vanry\Scout\TNTSearchScoutServiceProvider"

修改 .env 設定

SCOUT_DRIVER=tntsearch
SCOUT_QUEUE=false
TNTSEARCH_FUZZINESS=true
TNTSEARCH_BOOLEAN=true
TNTSEARCH_TOKENIZER=phpanalysis

模型使用 Trait 方法

<?php

namespace App\Models;

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;

use Laravel\Scout\Searchable;

class Post extends Model
{
    use HasFactory;
    use Searchable;

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

導入資料

# scout 命令
php artisan scout:import 'App\Models\Post'
# tntsearch 命令, 性能更好
php artisan tntsearch:import 'App\Models\Post'

搜尋資料

Post::search('laravel教程')->get();

注意事項

  • 中文分詞有三種方式 scws 、jieba 和 phpanalysis,預設使用 phpanalysis。
  • 使用 phpanalysis 在搜尋時,英文必須完整的字,例如:word 不能用 wo 來搜尋,中文字必須輸入兩個字以上才會搜尋到資料,不能只單一輸入一個中文字。例如:周杰倫,不能只輸入周字來查詢所有周姓。

目前僅測試 phpanalysis 分詞方式,其餘 scws 及 jieba 尚未測試。

最後修改日期: 2021 年 1 月 23 日