1

doctrine を 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 と doctrine の統合」について考える代わりに、「同じアプリケーションで doctrine と elasticsearch の両方を使用するにはどうすればよいか」について考えてください。

データベースでレコードを作成または更新するときはいつでも、ElasticsearchまたはSolrでそのデータのインデックスを作成したり、 MemcachedまたはRedisなどで既にキャッシュされた同じデータのバージョンをキャッシュまたは無効にしたりするなど、より多くの操作を実行する必要があります。それを適切に行うには (または zf2方法)、永続化操作と関連する後処理 (elasticsearch でのインデックス作成、キャッシュ、キャッシュの無効化、ログ記録など) の両方を調整するサービス レイヤーを慎重に設計する必要があります。

EventManagerを介していくつかのイベントを発生させることにより、これらの操作の一部を達成することは適切な決定です。

注: ログ行の書き込みなど、単純で単純なタスクに EventManager を多用しないでください。特にZF2では、イベントは無料ではありません。( ZF3 ではかなり改善されましたが、まだ無料ではありません)。


質問のために、 ruflin/elasticaであるサードパーティのライブラリを利用しながら Zend Framework 2 を使用する方法を次に示します。

A.端末を開いて入力します

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

B.エラスティカ クライアントのファクトリを作成する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.エラスティカ構成を追加し、新しいファクトリ クラスをサービス ロケータに登録します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 = $this->getServiceLocator()->get('elastica-client');

おまけ: サービス初期化子と特性の使用

PHP のバージョンが 5.4 以上の場合は、トレイトを使用しながら、サービスの初期化子を使用して Elastica Client をサービスに自動的に挿入できます。

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 マスター @Ocramius 自身から呼び出されたこのモジュールをチェックしてください :)OcraElasticSearch

そうでなければ、Doctrine と ElasticSearch の統合に関しては、Symfony2 が一歩先を行っているように見えます。

1 ~ 2 か月以内に、GitHub でさらに多くの代替手段を見つけることができるはずです。

近いうちに同様の機能が必要になるので、後でさらに発見するかもしれません。もしそうなら、私は自分の投稿を更新します。

于 2014-08-11T13:41:35.467 に答える