承接 heyday/silverstripe-elastica 相关项目开发

从需求分析到上线部署,全程专人跟进,保证项目质量与交付效率

邮箱:yvsm@zunyunkeji.com | QQ:316430983 | 微信:yvsm316

heyday/silverstripe-elastica

Composer 安装命令:

composer require heyday/silverstripe-elastica

包简介

Provides Elastic Search integration for SilverStripe DataObjects using Elastica

README 文档

README

Facilitates searching and indexing of SilverStripe CMS using ElasticSearch. We use Elastica to do all the heavy lifting in terms of communication with the elastic search server.

This module makes it easy to use ElasticSearch with SilverStripe without limiting any of the functionality found in Elastica. Basically anything that can be done with Elastica alone can be done in conjunction with this module.

This module supercedes Symbiote's Elastica Module, which was only supported up to SilverStripe 3.

Features

  • Uses Elastica to communicate with the ElasticSearch Server
  • Uses PSR/Log interface for logging purposes (optional)
  • Uses YAML configuration to index Data Objects and Pages
  • Can handle has_many, many_many, and has_one relationships in the indexed ElasticSearch document
  • Can handle invalidation and reindexing of related data objects
  • Can handle custom fields that are not in the database but only exist as part of an object instance
  • Infers ElasticSearch document field type from the database field type defined in the corresponding SilverStripe model

Compatibility

This release should be compatible with all ElasticSearch 9.0 and above versions. This release requires SilverStripe 6.x

Installation

$ composer require heyday/silverstripe-elastica

Usage

Elastica Service configuration example:

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:
    - hosts:
        - "`ELASTIC_URL`" # Define Elastic hosts e.g. https://HOST_NAME:PORT

  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

Index configuration example:

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

Custom field index configuration example:

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';
    }
}

Simple search controller configuration/implementation example:

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'));
    }
}

Reindexing

To run a full reindex of Elastica use

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

Subsite support

Our typical setup is to add SubsiteID as an indexed_field.

  indexed_fields:
    - ..
    - SubsiteID

And filter by this at query time.

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

$match = new \Elastica\Query\MultiMatch();
$match
    ->setQuery(strval($searchString))
    ->setFields($this->getESFields())
    ->setType('most_fields')
    ->setFuzziness('AUTO');
$bool->addMust($match);

$subsiteId = SubsiteState::singleton()->getSubsiteId();

if ($subsiteId) {
    $bool->addFilter(
        new \Elastica\Query\Term(['SubsiteID' => $subsiteId])
    );
} else {
    $bool->addFilter(
        new \Elastica\Query\Term(['SubsiteID' => 0])
    );
}

...

At indexing time

Using Queues

You can make use of queues to have your reindex processes run in the background.

We use silverstripe-queuedjobs (https://github.com/symbiote/silverstripe-queuedjobs) and a job to reindex on publish has been created.

To turn on queues, you will need the following config:

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

You will also need to set up a cronjob (I know not very queue-like...):

Every minute to run the jobs in the queue

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

and to clean up the jobs, add the cleanup job once by running (it then gets automatically added to run once a day):

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

heyday/silverstripe-elastica 适用场景与选型建议

heyday/silverstripe-elastica 是一款 基于 PHP 开发的 Composer 扩展包,目前已累计 38.53k 次下载、GitHub Stars 达 11, 最近一次更新时间为 2016 年 06 月 23 日, 在 PHP 生态内属于活跃度较高的组件。

它主要适用于以下技术方向: 「search」 「elastica」 「elasticsearch」 「silverstripe」 等业务场景。在实际项目中,围绕这些方向常见需要落地的问题包括:接口对接、性能调优、并发安全、与既有框架(Laravel / ThinkPHP / Yii / Webman 等)的兼容适配,以及生产环境的日志埋点与稳定性保障。

我们在过去多个企业项目中使用过 heyday/silverstripe-elastica 或与其功能相近的方案,如果你在选型或落地过程中遇到问题,例如 版本兼容、二次改造、私有化封装、与内部系统对接、生产 BUG 排查,欢迎联系我们协助评估。

围绕 heyday/silverstripe-elastica 我们能提供哪些服务?
定制开发 / 二次开发

基于 heyday/silverstripe-elastica 在你已有业务上做功能扩展、字段裁剪、UI 适配、与内部账号 / 权限 / 日志系统的深度对接。

BUG 修复 & 性能优化

线上偶发问题、内存泄漏、慢查询、并发异常等排查修复;针对高流量场景做缓存、队列、索引层面的调优。

项目外包 & 长期维护

承接完整的项目从需求 → 设计 → 开发 → 上线 → 长期运维;也可按月提供技术保姆服务。

yvsm@zunyunkeji.com QQ:316430983 微信:yvsm316 西安尊云信息科技 · 专注 PHP / Go / 分布式系统研发

统计信息

  • 总下载量: 38.53k
  • 月度下载量: 0
  • 日度下载量: 0
  • 收藏数: 11
  • 点击次数: 8
  • 依赖项目数: 2
  • 推荐数: 0

GitHub 信息

  • Stars: 11
  • Watchers: 21
  • Forks: 23
  • 开发语言: PHP

其他信息

  • 授权协议: BSD-3-Clause
  • 更新时间: 2016-06-23