shortcodes/scout-elasticsearch-driver

Laravel Scout 的 Elasticsearch 驱动程序

v5.0.2 2022-05-16 12:45 UTC

README

Packagist Packagist Gitter Donate

🍺 如果您喜欢我的包,您可以考虑 为我买一杯啤酒

:octocat: 项目在 Gitter 上有一个 聊天室

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

内容

功能

需求

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

  • PHP 版本 >= 7.1.3
  • Laravel 框架版本 >= 5.6
  • Elasticsearch 版本 >= 6

安装

使用 composer 安装包

composer require babenkoivan/scout-elasticsearch-driver

配置

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

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 索引中执行搜索请求的能力,请使用以下命令

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 a model fields.
    protected $mapping = [
        'properties' => [
            'text' => [
                'type' => 'text',
                'fields' => [
                    'raw' => [
                        'type' => 'text',
                        'index' => 'not_analyzed',
                    ]
                ]
            ],
        ]
    ];
}

每个可搜索的模型代表一个 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();

如果您需要加载多个关系,您可以使用 with 方法

App\MyModel::search('phone') 
    ->with(['makers', 'company'])
    ->paginate();

除了标准功能外,此包还为您提供了一种在不指定查询字符串的情况下在 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();

如果您想要发送自定义排序,可以使用 orderByScript 方法

App\MyModel::search('*')->orderByScript([
    'script' => [
        'lang' => 'groovy',
        'inline' => "
            def rank = 1;
            if (doc['price'].value) {
                rank += doc['total_view'].value*1+doc['total_like'].value*4+doc['total_download'].value*64;
            } else {
                rank += doc['total_view'].value*1+doc['total_like'].value*8+doc['total_download'].value*16;
            }
            return rank;
        "
    ],
    'type' => 'number',
    'order' => 'desc'
])->paginate();

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

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

除了标准功能外,此包还为您提供了一种在不指定查询字符串的情况下在 Elasticsearch 中聚合数据的方法

App\MyModel::search('*')
    ->aggregate();

除了标准功能外,此包还为您提供了一种在指定查询字符串的情况下使用 Elasticsearch 推荐数据的方法

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

除了标准功能外,此包还为您提供了一种在指定查询字符串的情况下使用 Elasticsearch 突出显示数据的方法

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

此查询将返回原始响应。

控制台命令

以下列出了可用的 artisan 命令

要获取详细说明和所有可用选项,请在命令行中运行 php artisan help [命令]

搜索规则

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

php artisan make:search-rule MySearchRule

在文件 app/MySearchRule.php 中,您将找到一个类定义

<?php

namespace App;

use ScoutElastic\SearchRule;

class MySearchRule 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();

聚合规则

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

php artisan make:aggregate-rule MyAggregateRule

在文件 app/MyAggregateRule.php 中,您将找到一个类定义

<?php

namespace App;

use ScoutElastic\AggregateRule;

class MyAggregateRule extends AggregateRule
{
    // This method returns an array that represents a content of bool query.
    public function buildAggregatePayload()
    {
        return [
            'icon_count' => [
                'terms' => [
                    'field' => 'icon_id',
                    'size' => 15
                ]
            ],
            'style_count' => [
                'terms' => [
                    'field' => 'style_id',
                    'size' => 7
                ]
            ],
            'category_count' => [
                'terms' => [
                    'field' => 'category_id',
                    'size' => 39
                ]
            ]
        ];
    }
}

您可以在 这里 了解更多关于聚合查询的信息。

要确定模型默认聚合规则,只需添加一个属性

<?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 $aggregateRules = [
        MyAggregateRule::class
    ];
}

建议规则

建议规则是一个类,用于描述建议查询的执行方式。要创建一个建议规则,使用以下命令:

php artisan make:suggest-rule MySuggestRule

在文件 app/MySuggestRule.php 中,你可以找到一个类定义。

<?php

namespace App;

use ScoutElastic\SuggestRule;

class MySuggestRule extends SuggestRule
{
    // This method returns an array that represents a content of bool query.
    public function buildSuggestPayload()
    {
        $query = $this->builder->query;

        if (empty($query)) {
            return null;
        }

        return [
            'text' => $query,
            'autocomplete' => [
                'prefix' => $query,
                'completion' => [
                    'field' => 'name.suggest_autocomplete',
                    'size' => 7
                ],
            ],
            'phrase-suggest' => [
                'phrase' => [
                    'field' => 'name.suggest_phrase.trigram',
                    'gram_size' => 3,
                    'direct_generator' => [
                        [
                            'field' => 'name.suggest_phrase.trigram',
                            'suggest_mode' => 'always'
                        ],
                        [
                            'field' => 'name.suggest_phrase.reverse',
                            'suggest_mode' => 'always',
                            'pre_filter' => 'reverse',
                            'post_filter' => 'reverse'
                        ],
                    ],
                    'highlight' => [
                        'pre_tag' => '<em>',
                        'post_tag' => '</em>'
                    ]
                ]
            ]
        ];
    }
}

你可以在这里了解更多关于建议查询的信息。

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

<?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 $suggestRules = [
        MySuggestRule::class
    ];
}

高亮规则

高亮规则是一个类,用于描述如何执行高亮查询。要创建高亮规则,使用以下命令:

php artisan make:hightlight-rule MyHightlightRule

在文件 app/MyHightlightRule.php 中,你可以找到一个类定义。

<?php

namespace App;

use ScoutElastic\HightlightRule;

class MyHightlightRule extends HightlightRule
{
    // This method returns an array that represents a content of bool query.
    public function buildHightlightPayload()
    {
        return [
            'fields' => [
                'name' => [
                    'force_source' => true
                ]
            ]
        ];
    }
}

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

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

<?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 $hightlightRules = [
        MyHightlightRule::class
    ];
}

To retrieve highlight, use model `highlight` attribute:

```php
// 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();

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