mikemadisonweb/yii2-elasticsearch

为与Elasticsearch版本5.0及以上版本集成而设计的Yii2扩展。

安装次数: 3,499

依赖项: 0

建议者: 0

安全: 0

星标: 16

关注者: 5

分支: 2

公开问题: 0

类型:yii2-extension

1.2.1 2017-11-04 07:56 UTC

This package is auto-updated.

Last update: 2024-08-29 04:47:56 UTC


README

基于官方elasticsearch-php低级客户端的Yii2扩展,用于与Elasticsearch版本5.0及以上版本集成。

elasticsearch-php相比,此扩展提供了更直观的操作方式,例如索引文档、搜索、倒排搜索(反向搜索)、使用简单的SQL-like语言构建复杂的过滤条件。此外,它高度可配置和可扩展,它不紧密绑定到ActiveRecord模型,但可以轻松实现。

此文档适用于该扩展的最新稳定版本。

Latest Stable Version License

安装

安装此扩展的首选方式是通过composer

运行以下命令

php composer.phar require mikemadisonweb/yii2-elasticsearch

"mikemadisonweb/yii2-elasticsearch": "^1.2.0"

将以下内容添加到您的composer.json文件的require部分。

配置

假设您有一个庞大的博客文章数据库,并且您想在标题和正文字段上使用全文搜索,也可以按关键词搜索,也许还需要按类别和标签进行过滤

<?php
// config/main.php
return [
    // ...
    'components'    => [
        // ...
        'elasticsearch'  => [
            'class' => \mikemadisonweb\elasticsearch\Configuration::class,
            'clients' => [
                'default' => [
                    'hosts' => [
                        'server1.yourdomain.com',
                        'server2.yourdomain.com:9200', 
                    ],
                ],
            ],
            'indexes' => [
                [
                    'index' => 'my-blog',
                    'client' => [
                        'name' => 'default',
                    ],
                    'body' => [
                        'settings' => [
                            'number_of_shards' => 5,
                            'number_of_replicas' => 1,
                        ],
                        'mappings' => [
                            'posts' => [
                                'dynamic' => 'strict', // Validate upon indexing, optional
                                'properties' => [
                                    'title' => [
                                        'type' => 'text',
                                    ],
                                    'body' => [
                                        'type' => 'text',
                                    ],
                                    'keywords' => [
                                        'type' => 'keyword',
                                    ],
                                    'category_id' => [
                                        'type' => 'integer',
                                        'include_in_all' => false,
                                    ],
                                    'tags' => [
                                        'type' => 'integer',
                                        'include_in_all' => false,
                                    ],
                                    'post_date' => [
                                        'type' => 'date',
                                        'format' => 'epoch_second', // timestamp
                                        'include_in_all' => false,
                                    ],
                                ],
                            ],
                        ],
                    ],
                ],
            ],
        ],
        // ...
    ],
    // ...
];

如果您需要,可以配置多个Elasticsearch客户端。这可能是您的应用程序使用的不同搜索集群。每个客户端可以定义为多个hosts,此参数包含Elasticsearch服务器的主机或IP地址列表,可选地后跟端口号(默认为9200)。您可以在elasticsearch-php文档中找到更多选项。默认情况下,连接到这些服务器之一使用轮询策略。

在选择分片和副本的数量时,请考虑您的性能和持久性需求。这些参数的正确数量是这些特性的折衷。上述示例使用默认的分片和副本数量,因此如果您希望这样,可以在配置中省略这些参数。

指定索引名称和该索引所使用的客户端后,您需要指定所需的搜索字段。这些字段可以根据您认为合理和方便的方式分组到映射中(例如,'posts')。在全文搜索方面,添加到名为索引的任何单个数据称为文档。理解映射意义的一个简单方法是将其视为文档类型。默认情况下,Elasticsearch不会强制您为您的数据提供此类模式,因此如果您的文档包含比映射中列出的更多字段,则这些新字段也会无问题地存储。要更改此行为,可以将dynamic设置为strict,在插入时未指定的字段将引发错误。

当您插入新文档时,每个字段都根据其数据类型进行处理。例如,text数据类型用于索引全文值(这些值将被分析),而keyword可以按其确切值进行搜索,这对于过滤或聚合很有用。请注意,如果您想存储数组,无需显式定义array数据类型,您可以在integer数据类型中存储整数数组。

默认情况下,Elasticsearch在索引时会存储传入的文档,当您检索搜索结果时,您将在_source字段中找到原始内容。您可以通过设置映射配置中的参数来禁用该行为。

'_source' => [
    'enabled' => true
],

另一方面,您可以在特定的映射字段中设置'index' => false以防止该字段被索引。

Elasticsearch还有一个特殊的_all字段,它将所有其他字段的值连接起来。当您未指定要搜索的字段列表时,会使用它,但它不会存储。

该扩展包含控制台命令,用于根据配置创建和删除索引。

<?php
// config/main.php
return [
    // ...
    'controllerMap' => [
        'elastic-index' => \mikemadisonweb\elasticsearch\commands\IndexController::class,
    ],
    // ...
];

用法

创建索引

配置完您的索引后,可以在Elasticsearch中创建它们。

php yii elastic-index/create 'my-blog'

如果您不提供索引名称,它将创建所有定义的索引。

索引文档

创建索引后,您可以像这样插入新记录

$indexer = \Yii::$app->elasticsearch->getIndexer('my-blog', 'posts');
$blogPost = [
    'title' => 'New in Elasticsearch 6.0',
    'body' => 'Lots of stuff...',
    'keywords' => 'Elasticsearch',
    'category_id' => '3',
    'tags' => [1, 43, 64],
];
$this->indexer->insert($blogPost);

插入方法有一个可选的第二个参数 - 一个唯一的id。您可以使用任何字符串作为id,每个索引中的文档都有一个该id,如果不传递该id,则Elasticsearch会自动生成。

Indexer类中的其他有用方法

IndexerResponse update(array $fields, string $id, array $upsert = [], $script = '', array $scriptParams = [])
IndexerResponse delete(string $id, bool $ignoreMissing = false)
array           insertBatch(array $batch)

批量插入是一种加快索引过程的方法,并且是唯一返回数组而不是ElasticResponse对象的函数。批量中的文档数组可以是数字(不带id)或关联的,以id作为键。

搜索

该扩展提供了一个构建器,用于简化查询组合的过程。要对'title'字段执行全文搜索,您应使用match()方法。

$finder = \Yii::$app->elasticsearch->getFinder('my-blog', 'posts');
$results = $finder
    ->match('How to use Elasticsearch', 'title')
    ->all();

还有过滤结果、排序或选择特定部分的方法。

$finder = \Yii::$app->elasticsearch->getFinder('my-blog', 'posts');
$results = $finder
    ->select(['title', 'body'])
    ->match('How to use Elasticsearch', 'title')
    ->where('category_id = 14')
    ->sort('post_date:desc')
    ->limit(100)
    ->offset(100)
    ->all();
    
foreach ($results as $result) {
    // ...
}

请注意,如果您在where()方法中使用分析字段(全文字段),可能会得到错误的结果,因为该方法仅适用于非分析数据类型(keyword、integer、boolean等)。match()方法中有一个可选参数,您必须注意。

Finder match(string $query, array|string $fields = '_all', string $condition = 'and', string $operator = 'and', string $type = 'cross_fields')

通常需要将查询字符串与特定字段匹配,但如果您想在不同的字段中搜索不同的字符串(例如,在'title'中搜索'some text'和在'body'中搜索'another data'),则可以在condition参数中选择逻辑运算符以满足您的需求。如果您在多个字段中进行搜索,可以定义operatortype参数以指定在这些字段上搜索的逻辑

更复杂的过滤器可以使用类似SQL的方式指定。

$finder = \Yii::$app->elasticsearch->getFinder('my-blog', 'posts');
$results = $finder
    ->where("category_id = 11 OR (tags in [1, 53, 78] AND keywords = 'Elastica')")
    ->all();

如果您觉得Finder方法有限,可以传递原始JSON并直接与Elasticsearch API交互。

$json = '{
    "query" : {
        "match" : {
            "body" : "Most important things in life"
        }
    }
}';
$finder = \Yii::$app->elasticsearch->getFinder('my-blog', 'posts');
$results = $finder->sendJson($json);

分析

Elasticearch为分析文本提供了大量选项。分析器、规范化器和令牌过滤器超出了本文档的范围,您可以在官方文档中找到有关它们的大量信息。

以下是一个带有停用词过滤器和snowball词干还原器的俄语分析配置示例。

<?php
// config/main.php
return [
    // index settings
    'settings' => [
        'number_of_shards' => 1,
        'number_of_replicas' => 0,
        'analysis' => [
            'filter' => [
                'russian_stop' => [
                    'type' => 'stop',
                    'stopwords' => '_russian_',
                ],
                'russian_stemmer' => [
                    'type' => 'stemmer',
                    'language' => 'russian',
                ],
            ],
            'analyzer' => [
                'default' => [
                    'tokenizer' => 'standard',
                    'filter' => [
                        'lowercase',
                        'russian_stop',
                        'russian_stemmer',
                    ],
                ],
            ],
        ],
    ],
    // ...
];

高亮显示

Elasticsearch提供了一种在源文本中突出显示搜索词的方式。如果你搜索“新的可能性”,那么某些文档中找到的“可能性”这个词会被像这样用标签包围<em>可能性</em>。这些突出显示的结果将位于响应的“highlight”字段中,而不是“_source”字段中。有一个名为highlight()的Finder方法,可以用于为单个查询开启此功能。你还可以将各种参数作为第二个参数传递

<?php
$finder = \Yii::$app->elasticsearch->getFinder('my-blog', 'posts');
$results = $finder
    ->match('Find me!', 'body')
    ->highlight(true, [
        'fields' => [
            'body' => new \stdClass()
        ],
        'pre_tags' => '<strong>',
        'post_tags' => '</strong>',
        ])
    ->all();

要全局开启此功能,你应在索引配置中启用它。默认排序顺序和限制选项也可以在那里进行配置

<?php
// config/main.php
return [
    // index configuration
    'index' => 'my-blog',
    'defaults' => [
        'limit' => 100,
        'sort' => 'post_date:desc',
        'highlight' => [
            'enabled' => true,
            'pre_tags' => '<span class=“highlight”>',
            'post_tags' => '</span>',
            'fields' => ['*' => ['number_of_fragments' => 0]]
        ],
    ],
    // ...
];

星号符号表示将在所有配置的分析字段中突出显示,但有一个问题。如果你想接收所有文本字段的突出显示结果,那么你不应该在match()函数中将_all作为搜索字段传递。