1

我按照本教程将教义与 Zend Framework 2 集成。现在,一切正常,但我想将 Elasticsearch 集成到这个项目中。

我找到了很多关于 Elasticsearch 的文档,我下载了 PHP 的 Elastica 插件,但我不知道从哪里开始。

我搜索了将 Elasticsearch 与 Doctrine 集成的教程,但它们都是关于 Symfony 的。有人可以(以简单的方式)解释我如何在 Zend Framework 2 中使用 ElasticSearch,使用 Doctrine 2 作为 ORM 来索引和搜索我的对象吗?

4

2 回答 2

19

Doctrine 2Elasticsearch之间没有直接关系。Doctrine ORM 的主要关注点是持久化、更新和读取关系数据库上的数据,而 elasticsearch 主要关注索引和搜索数据。与其考虑“将 elasticsearch 与学说集成”,不如考虑“如何在同一应用程序中同时使用学说和 elasticsearch”

每当您在数据库中创建或更新记录时,您可能希望执行更多操作,例如在ElasticsearchSolr上索引该数据,在MemcachedRedis上缓存或使已缓存的相同数据版本无效等。正确地做到这一点(或 zf2方式),您应该仔细设计一个服务层,该服务层协调持久性操作和相关的后处理,如弹性​​搜索上的索引、缓存、缓存失效、日志记录等。

通过EventManager触发一些事件来完成其中一些操作将是一个合适的决定。

注意:不要将 EventManager 大量用于简单直接的任务,例如编写日志行。活动不是免费的,尤其是在 ZF2 中。(在 ZF3 中相当改进,但仍然不是免费的)。


作为问题,这是在使用ruflin/elastica的 3rd 方库时使用 Zend Framework 2 的方法:

A.打开你的终端并输入

$ cd /path/to/your/project
$ php composer.phar selfupdate
$ php composer.phar require ruflin/elastica:dev-master

B.为elastica客户端创建工厂Application\Service\ElasticaClientFactory.php

<?php
namespace Application\Service;

use Zend\ServiceManager\FactoryInterface;
use Zend\ServiceManager\ServiceLocatorInterface;

class ElasticaClientFactory implements FactoryInterface
{
    public function createService(ServiceLocatorInterface $sl)
    {
        $config = $sl->get('Config');
        $clientOptions = isset($config['elastica']) ? $config['elastica'] : array();
        $client = new \Elastica\Client($clientOptions);

        return $client;
    }
}

C.添加 elastica 配置并将新工厂类注册到您的服务定位器module.config.php

'elastica' => array(
    'servers' => array(
        array('host' => '127.0.0.1','port' => 9200),
        // You can add more servers when necessary
        // array('host' => '127.0.0.1','port' => 9200)
        ),
    ),

service_manager' => array(
    'factories' => array(
        'elastica-client' => 'Application\Service\ElasticaClientFactory'
    ),
)

此时,在任何控制器(坏)或服务(好)中,您都可以像这样获取 elastica 客户端实例:

$elastica = $this->getServiceLocator()->get('elastica-client');

奖励:使用服务初始化器和特征

如果您的 PHP 版本 ≥ 5.4,您可以使用特征,同时借助服务初始化程序自动将 Elastica 客户端注入您的服务。

D.创建一个名为的新接口Application\Service\ElasticaAwareInterface.php

<?php
namespace Application\Service;

interface ElasticaAwareInterface
{
    public function getElasticaClient();
    public function setElasticaClient(\Elastica\Client $client);
}

E.创建一个名为的新特征Application\Traits\ElasticaAwareTrait.php(注意路径。如果不存在,则创建特征文件夹)

<?php
namespace Application\Traits;

trait ElasticaAwareTrait
{
    protected $client = null;

    public function getElasticaClient()
    {
        return $this->client;
    }

    public function setElasticaClient(\Elastica\Client $client)
    {
        $this->client = $client;
        return $this;
    }
}

F.创建一个名为Application\Initializers\ElasticaInitializer.php(再次注意路径)的新初始化程序

<?php
namespace Application\Initializers;

use Zend\ServiceManager\InitializerInterface;
use Zend\ServiceManager\ServiceLocatorInterface;
use Application\Service\ElasticaAwareInterface;

class ElasticaInitializer implements InitializerInterface
{
    /**
     * Initializer for the elastica-aware domain services.
     * Properly creates a new elastica client and injects it into related service.
     */
    public function initialize($service, ServiceLocatorInterface $serviceManager)
    {
        /**
         * Beware: This if statement will be run for every service instance
         * we grab from $serviceManager because the nature of initializers.
         * This worth think about on it. With ZF3 this went further. 
         * We may load our services lazily using delegator factories.
         */ 
        if ($service instanceof ElasticaAwareInterface) {
            $service->setElasticaClient( $serviceManager->get('elastica-client') );
        }
    }
}

到现在为止还挺好。现在,我们可以将所有部分放在一起。比如说,我们有一个名为的服务UserService,它使用 Doctrine 实体管理器(或者更好的 UserRepository),也需要使用Elastica

G.向服务经理注册我们的服务:

service_manager' => array(
    'factories' => array(
        'elastica-client' => 'Application\Service\ElasticaClientFactory'
    ),
    'invokables' => array(
        'user-service' => 'Application\Service\UserService'
    )
)

最后是UserService签名:

<?php
namespace Application\Service;

use Application\Service\ElasticaAwareInterface;

class UserService implements ElasticaAwareInterface
{
    // Here is our trait
    use \Application\Traits\ElasticaAwareTrait;

    public function fooMethod()
    {
        // Do some things with doctrine EM here..

        // And grab the elastica client easily anywhere in UserService
        $client = $this->getElasticaClient();
    }
}
于 2014-08-11T15:39:27.713 回答
0

有一些(仍在大量开发中)模块结合了 Doctrine2 和 ElasticSearch。例如查看从 Doctrine2+ZF2 Master @Ocramius 本人调用的这个模块:)OcraElasticSearch

否则,在集成 Doctrine 和 ElasticSearch 方面,Symfony2 似乎领先一步。

我敢打赌,在一两个月内,您应该能够在 GitHub 上找到更多替代方案。

由于我们很快需要类似的功能,我以后可能会发现更多。如果我这样做,我会更新我的帖子。

于 2014-08-11T13:41:35.467 回答