baril/sqlout

Laravel Scout 的 MySQL 全文搜索驱动。

v5.0.0 2023-12-27 09:14 UTC

This package is auto-updated.

Last update: 2024-08-31 00:35:37 UTC


README

Sqlout 是一个针对 Laravel Scout 的非常简单的 MySQL 驱动。它将数据索引到 MySQL 数据库的专用表中,并使用全文索引进行搜索。它适用于小型项目,对于需要更大解决方案(如 ElasticSearch)的项目来说可能过于冗余。

Sqlout 与 Scout 9 的原生 Database 引擎不同,因为它将数据索引到单独的专用表中,并使用全文索引。Sqlout 还具有更多功能,例如字段权重和词干提取。

Sqlout 与 Laravel 5.8+ 到 10.x 和 Scout 7.1+ / 8.x / 9.x / 10.x 兼容(感谢 ikari7789 为 Laravel 9 和 10 / Scout 9 和 10 提供支持)。

版本兼容性

设置

需要此包

composer require baril/sqlout

发布配置

php artisan vendor:publish

如果您不使用包发现,请手动将服务提供者(Scout 和 Sqlout 的)添加到您的 config/app.php 文件中

return [
    // ...
    'providers' => [
        // ...
        Laravel\Scout\ScoutServiceProvider::class,
        Baril\Sqlout\SqloutServiceProvider::class,
    ],
];

迁移您的数据库

php artisan sqlout:make-migration
php artisan migrate

这将创建一个名为 searchindex 的表(表名可以在配置文件中自定义)。

如果您想索引属于不同连接的模型,您需要在每个连接上创建一个 Sqlout 表。要创建非默认连接上的表,您可以调用 sqlout:make-migration 命令并传递连接名

php artisan sqlout:make-migration my_other_connection
php artisan migrate

使模型可搜索

use Baril\Sqlout\Searchable;

class Post extends Model
{
    use Searchable;

    protected $weights = [
        'title' => 4,
        'excerpt' => 2,
    ];

    public function toSearchableArray()
    {
        return [
            'title' => $this->post_title,
            'excerpt' => $this->post_excerpt,
            'body' => $this->post_content,
        ];
    }
}

上面的示例类似于在 Scout 文档 中描述的内容,但有以下差异/添加内容

  • 您会注意到该模型使用的是 Baril\Sqlout\Searchable 特性,而不是 Laravel\Scout\Searchable
  • 可以使用 $weight 属性来“增强”某些字段。默认值是 1。

完成这些后,您可以使用 Scout 的 Artisan 命令索引您的数据

php artisan scout:import "App\Post"

您的模型在保存时也会自动索引。

搜索

基础

$results = Post::search('this rug really tied the room together')->get();
$results = Post::search('the dude abides')->withTrashed()->get();

有关更多详细信息,请参阅 Scout 文档

Sqlout 的构建器还提供了以下附加方法

// Restrict the search to some fields only:
$builder->only('title');
$builder->only(['title', 'excerpt']);
// (use the same names as in the toSearchableArray method)

// Retrieve the total number of results:
$nbHits = $builder->count();

使用作用域

使用 Sqlout,您还可以在搜索构建器上使用您的模型作用域,就像它在模型本身上的查询构建器一样。同样,所有对搜索构建器上的 where 方法的调用都将转发到模型的查询构建器。

$results = Post::search('you see what happens larry')
    ->published() // the `published` scope is defined in the Post class
    ->where('date', '>', '2010-10-10')
    ->get();

⚠️ 请记住,这些转发的范围实际上将应用于子查询(主查询是 searchindex 表上的查询)。这意味着例如添加 order by 子句的范围没有任何效果。有关正确排序结果的方法,请参阅下面。

如果您的范围名称与 Baril\Sqlout\Builder 对象的方法名称冲突,您可以将您的范围包装在 scope 方法中

$results = Post::search('ve vant ze money lebowski')
    ->scope(function ($query) {
        $query->within('something');
    })
    ->get();

搜索模式

MySQL 的全文搜索有 3 种口味

  • 自然语言模式,
  • 带有查询扩展的自然语言模式,
  • 布尔模式。

Sqlout 的默认模式是“自然语言”(但可以在配置文件中更改)。

您还可以通过以下方法在每个查询的基础上在所有 3 种模式之间进行切换

$builder->inNaturalLanguageMode();
$builder->withQueryExpansion();
$builder->inBooleanMode();

排序结果

如果没有指定排序,结果将按得分排序(最相关优先)。但您也可以按表格中的任何列排序结果。

$builder->orderBy('post_status', 'asc')->orderByScore();
// "post_status" is a column of the original table

在下面的示例中,结果将首先按状态排序,然后按得分降序排列。

过滤器、分词器、停用词和词干提取

在您的配置文件中,您可以自定义索引内容和搜索词的处理方式

return [
    // ...
    'sqlout' => [
        // ...
        'filters' => [ // anything callable (function name, closure...)
            'strip_tags',
            'html_entity_decode',
            'mb_strtolower',
            'strip_punctuation', // this helper is provided by Sqlout (see helpers.php)
        ],
        'token_delimiter' => '/[\s]+/',
        'minimum_length' => 2,
        'stopwords' => [
            'est',
            'les',
        ],
        'stemmer' => Wamania\Snowball\Stemmer\French::class,
    ],
];

在示例中,词干提取器来自包 wamania/php-stemmer,但任何具有 stem 方法的类,或者任何可调用的东西,例如闭包,都可以。