haunt-jonathan/heyday-silverstripe-elastica

使用Elastica为SilverStripe DataObjects提供Elastic Search集成

安装: 331

依赖项: 0

建议者: 0

安全: 0

星级: 0

关注者: 0

分支: 22

类型:silverstripe-vendormodule

4.1 2022-11-13 20:12 UTC

This package is not auto-updated.

Last update: 2024-10-01 03:59:15 UTC


README

该模块简化了使用ElasticSearch进行SilverStripe CMS搜索和索引的过程。我们使用Elastica来处理与ElasticSearch服务器通信的所有繁重任务。

此模块使您能够轻松地在SilverStripe中使用ElasticSearch,同时不会限制Elastica中的任何功能。基本上,任何仅使用Elastica即可完成的事情,都可以与该模块一起完成。

此模块取代了Symbiote的Elastica模块,该模块仅支持SilverStripe 3。

功能

  • 使用Elastica与ElasticSearch服务器通信
  • 使用PSR/Log接口进行日志记录(可选)
  • 使用YAML配置来索引数据对象和页面
  • 可以处理索引的ElasticSearch文档中的has_many、many_many和has_one关系
  • 可以处理相关数据对象的失效和重新索引
  • 可以处理作为对象实例一部分但不在数据库中的自定义字段
  • 从相应的SilverStripe模型中定义的数据库字段类型推断ElasticSearch文档字段类型

兼容性

此版本应与所有ElasticSearch 7.0及以上版本兼容。可能适用于Elasticsearch 6。此版本需要SilverStripe 4.x

如果您需要使用早期版本的elasticsearch(2.x)和SS(3.x),请尝试此模块的1.0版本

安装

$ composer require heyday/silverstripe-elastica

用法

Elastica服务配置示例

mysite/_config/search.yml

Heyday\Elastica\ElasticaService: # Example of customising the index config on the elastic search server (completely optional).
  index_config:
    settings:
      analysis:
        analyzer:
          default:
            type: custom
            tokenizer: standard
            filter:
              - lowercase
              - stemming_filter
        filter:
          stemming_filter:
            type: snowball
            language: English

---
Only:
  environment: dev
---
SilverStripe\Core\Injector\Injector:
  Elastica\Client:
    constructor:
      - host: localhost # hostname of the elastic search server
        port: 9200 # port number of the elastic search server

  Heyday\Elastica\ElasticaService:
    constructor:
      - "%$Elastica\Client"
      - "name-of-index"  # name of the index on the elastic search server
      - "%$Logger"  # your error logger (must implement psr/log interface)
      - "64MB"      # increases memory limit while indexing

索引配置示例

mysite/_config/search.yml

# PageTypes

Your\Namespace\Page:
  extensions:
    - Heyday\Elastica\Searchable
  indexed_fields: &page_defaults
    - Title
    - MenuTitle
    - Content
    - MetaDescription

Your\Namespace\SpecialPageWithAdditionalFields:
  extensions:
    - Heyday\Elastica\Searchable # only needed if this page does not extend the 'Page' configured above
  indexed_fields:
    <<: *page_defaults
    - BannerHeading
    - BannerCopy
    - SubHeading

Your\Namespace\SpecialPageWithRelatedDataObject:
  extensions:
    - Heyday\Elastica\Searchable
  indexed_fields:
    <<: *page_defaults
    -
      RelatedDataObjects:
        type: nested
        relationClass: App\DataObjects\Tags # Will be pulled from has_many / many_many, but you can specify it here too

Your\Namespace\RelatedDataObject:
  extensions:
    - Heyday\Elastica\Searchable
  indexed_fields:
    - Title
    - SomeOtherField
  dependent_classes:
    - SpecialPageWithRelatedDataObject # invalidates the index for SpecialPageWithRelatedDataObject when a RelatedDataObject is updated/created

自定义字段索引配置示例

mysite/_config/search.yml

# PageTypes

Your\Namespace\Page:
  extensions:
    - Heyday\Elastica\Searchable
  indexed_fields:
    - Title
    - SomeOtherField
    -
      TitleAlias:
        type: text
        field: Title # You can specify a custom internal field value with 'field'
    -
      SomeCustomFieldSimple:
        type: text
    -
      SomeCustomFieldComplicatedConfig:
        type: text
        analyzer: nGram_analyser # Must reference analyzer defined on index_config
        search_analyzer: whitespace_analyser # Must reference analyzer defined on index_config
        store: true

mysite/code/PageTypes/Page.php

<?php

class Page extends SiteTree
{
    public function getSomeCustomFieldSimple()
    {
        return 'some dynamic text or something';
    }

    public function getSomeCustomFieldComplicatedConfig()
    {
        return 'the config does not have anyting to do with me';
    }
}

简单搜索控制器配置/实现示例

mysite/_config/search.yml

  SearchController:
    properties:
      SearchService: "%$Heyday\Elastica\ElasticaService"

mysite/code/Controllers/SearchController.php

<?php

class SearchController extends Page_Controller
{
    /**
     * @var array
     */
    private static $allowed_actions = [
        'index'
    ];

    /**
     * @var \Heyday\Elastica\ElasticaService
     */
    protected $searchService;

    /**
     * Search results page action
     *
     * @return HTMLText
     */
    public function index()
    {
        return $this->renderWith(['SearchResults', 'Page']);
    }

    /**
     * @param \Heyday\Elastica\ElasticaService $searchService
     */
    public function setSearchService(\Heyday\Elastica\ElasticaService $searchService)
    {
        $this->searchService = $searchService;
    }

    /**
     * @return bool|\Heyday\Elastica\PaginatedList
     */
    public function Results()
    {
        $request = $this->getRequest();

        if ($string = $request->requestVar('for')) {

            $query = new \Elastica\Query\BoolQuery();

            $query->addMust(
                new \Elastica\Query\QueryString(strval($string))
            );

            $results = $this->searchService->search($query);

            return new \Heyday\Elastica\PaginatedList($results, $request);
        }

        return false;
    }

    /**
     * Query all Page fields and RelatedObjects nested fields.
     *
     * @return bool|\SilverStripe\ORM\PaginatedList
     */
    public function ResultsWithRelatedObjects()
    {
        $request = $this->getRequest();

        if ($string = $request->requestVar('for')) {

            $queryString = new \Elastica\Query\QueryString(strval($string));

            $boolQuery = new \Elastica\Query\BoolQuery();

            $nestedQuery = new \Elastica\Query\Nested();
            $nestedQuery->setPath('RelatedDataObjects');
            $nestedQuery->setQuery($queryString);

            $boolQuery->addShould($queryString);
            $boolQuery->addShould($nestedQuery);

            $results = $this->searchService->search($boolQuery);

            return new \SilverStripe\ORM\PaginatedList($results, $request);
        }

        return false;
    }

    /**
     * @return mixed
     */
    public function SearchString()
    {
        return Convert::raw2xml($this->getRequest()->requestVar('for'));
    }
}

重新索引

要运行Elastica的完整重新索引,请使用

./vendor/bin/sake dev/tasks/ElasticaReindexTask

使用队列

您可以使用队列使重新索引过程在后台运行。

我们使用silverstripe-queuedjobs (https://github.com/symbiote/silverstripe-queuedjobs) 创建了一个用于在发布时重新索引的工作。

要启用队列,您需要以下配置

SilverStripe\Core\Injector\Injector:
  Heyday\Elastica\Searchable:
    properties:
      queued: true

您还需要设置一个cronjob(我知道这不是非常队列式的...)

每分钟运行队列中的作业

*/1 * * * * php /path/to/silverstripe/framework/cli-script.php dev/tasks/ProcessJobQueueTask

要清理作业,通过运行(它然后会自动添加为每天运行一次)添加清理作业一次

framework/sake dev/tasks/CreateQueuedJobTask?name=Symbiote\QueuedJobs\Jobs\CleanupJob