jackardios/scout-elasticsearch-driver

Laravel Scout 的 Elasticsearch 驱动

v4.2.4 2020-10-02 03:26 UTC

README

Packagist Packagist Build Status Donate

🍺 如果您喜欢我的包,您可以通过购买一杯啤酒来支持我。

此包提供对 Elasticsearch 中数据搜索和过滤的高级功能。查看其功能

内容

功能

  • 一种简单的方法来 配置创建 Elasticsearch 索引。
  • 为每个 模型 提供完全可配置的映射。
  • 可以在现有映射中自动添加新字段或使用 Artisan 命令
  • 有多种不同的方式来实现您的搜索算法:使用 搜索规则 或原始搜索。
  • 提供各种 过滤器类型,使搜索查询更具体。
  • 从旧索引到新索引的 零停机迁移
  • 批量索引,请参阅配置部分

要求

该包已在以下配置中进行测试

  • PHP版本 >=7.1.3, <=7.3
  • Laravel 框架版本 >=5.8, <=6
  • Elasticsearch 版本 >=7

安装

使用 Composer 安装包

composer require jackardios/scout-elasticsearch-driver

如果您正在使用 Laravel 版本 <= 5.4 或 禁用包发现,请将以下提供者在 config/app.php 中添加

'providers' => [
    Laravel\Scout\ScoutServiceProvider::class,
    ScoutElastic\ScoutElasticServiceProvider::class,
]

配置

要配置包,您需要首先发布设置

php artisan vendor:publish --provider="Laravel\Scout\ScoutServiceProvider"
php artisan vendor:publish --provider="ScoutElastic\ScoutElasticServiceProvider"

然后,在 config/scout.php 文件中将驱动设置设置为 elastic,并在 config/scout_elastic.php 文件中配置驱动本身。可用选项包括

注意,如果您使用批量文档索引,您可能想要更改块大小,您可以在 config/scout.php 文件中这样做。

索引配置器

使用索引配置器类来设置 Elasticsearch 索引的设置。要创建新的索引配置器,请使用以下 artisan 命令

php artisan make:index-configurator MyIndexConfigurator

它将在您的项目的 app 文件夹中创建 MyIndexConfigurator.php 文件。您可以根据以下示例指定索引名称和设置

<?php

namespace App;

use ScoutElastic\IndexConfigurator;

class MyIndexConfigurator extends IndexConfigurator
{
    // It's not obligatory to determine name. By default it'll be a snaked class name without `IndexConfigurator` part.
    protected $name = 'my_index';  
    
    // You can specify any settings you want, for example, analyzers. 
    protected $settings = [
        'analysis' => [
            'analyzer' => [
                'es_std' => [
                    'type' => 'standard',
                    'stopwords' => '_spanish_'
                ]
            ]    
        ]
    ];
}

更多关于索引设置的详细信息,请参阅 Elasticsearch 文档中的索引管理部分

要创建索引,只需运行 artisan 命令

php artisan elastic:create-index "App\MyIndexConfigurator"

注意,每个可搜索模型都需要其自己的索引配置器。

在Elasticsearch 6.0.0或更高版本中创建的索引只能包含一个映射类型。在5.x版本中创建的包含多个映射类型的索引将继续在Elasticsearch 6.x中按之前的方式运行。在Elasticsearch 7.0.0中,映射类型将被完全移除。

更多信息请见这里

可搜索模型

要创建一个具有在Elasticsearch索引中执行搜索请求能力的模型,请使用以下命令:

php artisan make:searchable-model MyModel --index-configurator=MyIndexConfigurator

执行命令后,你将在你的app文件夹中找到MyModel.php文件。

<?php

namespace App;

use ScoutElastic\Searchable;
use Illuminate\Database\Eloquent\Model;

class MyModel extends Model
{
    use Searchable;

    protected $indexConfigurator = MyIndexConfigurator::class;

    protected $searchRules = [
        //
    ];

    // Here you can specify a mapping for model fields
    protected $mapping = [
        'properties' => [
            'title' => [
                'type' => 'text',
                // Also you can configure multi-fields, more details you can find here https://elastic.ac.cn/guide/en/elasticsearch/reference/current/multi-fields.html
                'fields' => [
                    'raw' => [
                        'type' => 'keyword',
                    ]
                ]
            ],
        ]
    ];
}

每个可搜索的模型代表一个Elasticsearch类型。默认情况下,类型名称与表名相同,但你可以通过searchableAs方法设置任何类型名称。你还可以通过toSearchableArray方法指定将由驱动程序索引的字段。关于这些选项的更多信息,你可以在Scout官方文档中找到。

MyModel类中可以设置的最后一个重要选项是$searchRules属性。它允许你为模型设置不同的搜索算法。我们将在搜索规则部分更详细地讨论它。

在你的模型中设置映射后,你可以更新Elasticsearch类型映射。

php artisan elastic:update-mapping "App\MyModel"

用法

一旦你创建了索引配置器、Elasticsearch索引和可搜索模型,你就可以开始使用了。现在,你可以根据文档进行索引搜索数据。

基本搜索用法示例

// set query string
App\MyModel::search('phone')
    // specify columns to select
    ->select(['title', 'price'])
    // filter 
    ->where('color', 'red')
    // sort
    ->orderBy('price', 'asc')
    // collapse by field
    ->collapse('brand')
    // set offset
    ->from(0)
    // set limit
    ->take(10)
    // get results
    ->get();

如果你只需要查询的匹配数量,请使用count方法

App\MyModel::search('phone') 
    ->count();

如果你需要加载关系,请使用with方法

App\MyModel::search('phone') 
    ->with('makers')
    ->get();

除了标准功能外,该包还提供了不指定查询字符串即可在Elasticsearch中过滤数据的可能性

App\MyModel::search('*')
    ->where('id', 1)
    ->get();

你也可以覆盖模型的搜索规则

App\MyModel::search('Brazil')
    ->rule(App\MySearchRule::class)
    ->get();

并且可以使用各种where条件

App\MyModel::search('*')
    ->whereRegexp('name.raw', 'A.+')
    ->where('age', '>=', 30)
    ->whereExists('unemployed')
    ->get();

并且过滤掉得分小于min_score的结果

App\MyModel::search('sales')
    ->minScore(1.0)
    ->get();

最后,如果你想发送一个自定义请求,你可以使用searchRaw方法

App\MyModel::searchRaw([
    'query' => [
        'bool' => [
            'must' => [
                'match' => [
                    '_all' => 'Brazil'
                ]
            ]
        ]
    ]
]);

此查询将返回原始响应。

控制台命令

以下列出了可用的Artisan命令

要在命令行中运行,请使用php artisan help [command]获取详细描述和所有可用选项。

搜索规则

搜索规则是一个描述如何执行搜索查询的类。要创建搜索规则,请使用以下命令

php artisan make:search-rule MySearchRule

在文件app/MySearchRule.php中,你将找到类定义。

<?php

namespace App;

use ScoutElastic\SearchRule;

class MySearch extends SearchRule
{
    // This method returns an array, describes how to highlight the results.
    // If null is returned, no highlighting will be used. 
    public function buildHighlightPayload()
    {
        return [
            'fields' => [
                'name' => [
                    'type' => 'plain'
                ]
            ]
        ];
    }
    
    // This method returns an array, that represents bool query.
    public function buildQueryPayload()
    {
        return [
            'must' => [
                'match' => [
                    'name' => $this->builder->query
                ]
            ]
        ];
    }
}

你可以在这里了解更多关于bool查询的信息,以及这里了解更多关于高亮显示的信息。

默认搜索规则返回以下有效负载

return [
   'must' => [
       'query_string' => [
           'query' => $this->builder->query
       ]
   ]
];

这意味着默认情况下,当你对模型调用search方法时,它会在任何字段中尝试找到查询字符串。

要确定模型的默认搜索规则,只需添加一个属性

<?php

namespace App;

use ScoutElastic\Searchable;
use Illuminate\Database\Eloquent\Model;

class MyModel extends Model
{
    use Searchable;
    
    // You can set several rules for one model. In this case, the first not empty result will be returned.
    protected $searchRules = [
        MySearchRule::class
    ];
}

你还可以在查询构建器中设置搜索规则

// You can set either a SearchRule class
App\MyModel::search('Brazil')
    ->rule(App\MySearchRule::class)
    ->get();
    
// or a callable
App\MyModel::search('Brazil')
    ->rule(function($builder) {
        return [
            'must' => [
                'match' => [
                    'Country' => $builder->query
                ]
            ]
        ];
    })
    ->get();

要获取高亮显示,请使用模型的highlight属性

// Let's say we highlight field `name` of `MyModel`.
$model = App\MyModel::search('Brazil')
    ->rule(App\MySearchRule::class)
    ->first();

// Now you can get raw highlighted value:
$model->highlight->name;

// or string value:
 $model->highlight->nameAsString;

可用过滤器

你可以使用不同类型的过滤器

在大多数情况下,最好使用原始字段来过滤记录,即未分析的字段。

零停机迁移

正如您可能知道的,在Elasticsearch中,您不能更改已创建字段的类型。在这种情况下,唯一的选择是创建一个新的索引,包含必要的映射,并将模型导入到新的索引中。
迁移可能需要相当长的时间,为了避免在迁移过程中出现停机时间,驱动程序从旧索引中读取并写入新索引。一旦迁移完成,它开始从新索引中读取并删除旧索引。这就是 artisan elastic:migrate 命令的工作方式。

在运行命令之前,请确保您的索引配置器使用了 ScoutElastic\Migratable 特性。如果不是,请添加该特性,并使用索引配置器类名作为参数运行 artisan elastic:update-index 命令。

php artisan elastic:update-index "App\MyIndexConfigurator"

准备好后,在模型映射中做出更改,并使用模型类作为第一个参数,所需索引名称作为第二个参数运行 elastic:migrate 命令。

php artisan elastic:migrate "App\MyModel" my_index_v2

注意,如果您只需在映射中添加新字段,请使用 elastic:update-mapping 命令。

调试

有两种方法可以帮助您分析搜索查询的结果:

  • explain

    App\MyModel::search('Brazil')
        ->explain();
  • profile

    App\MyModel::search('Brazil')
        ->profile();

这两种方法都返回来自ES的原始数据。

此外,您可以通过调用 buildPayload 方法来获取将被发送到ES的查询有效负载。

App\MyModel::search('Brazil')
    ->buildPayload();

注意,由于一个查询中可能使用多个搜索规则,此方法返回一个有效负载集合。