13

私は自分のプロジェクトで FOSElasticaBundle と Doctrine を使用しています。私のコードは、Doctrine ライフサイクル イベントを使用した選択的なインデックスの更新に対応しています。私が直面する問題は、関連するエンティティを個別に更新する場合です。

たとえば、人は、多対多の関係を通じて会社に関連付けられている場合があります。会社エンティティを介して会社名を直接更新すると、会社に関連する個人のインデックスは古くなり、会社の古い名前に関連付けられます。

これを処理する方法について少し迷っています。誰か提案はありますか?スケジュールされたインデックスの更新に頼って、その間に不正確なインデックス データに対処する必要がありますか、または更新されたエンティティに関連するエンティティの更新を呼び出す方法はありますか?

マッピングを確立するために JMSSerializer グループに依存しています。これが長期的に物事を行うための最良の方法ではないかもしれないことを理解しています.

4

7 に答える 7

4

このページで解決策を見つけたと思いますhttps://groups.google.com/forum/#!topic/elastica-php-client/WTONX-zBTI4 ありがとう Cassiano

基本的に、FOS\ElasticaBundle\Doctrine\ORM\Listener を拡張する必要があるため、関連するエンティティを探して、それらのインデックスも更新できます。

class CompanyListener extends BaseListener
{

    /** @var \Symfony\Component\DependencyInjection\ContainerInterface */
    private $container;

    public function setContainer(\Symfony\Component\DependencyInjection\ContainerInterface $container) {
        $this->container = $container;
    }

    protected function initialiseJob() {
        $this->objectPersisterJob = $this->container->get('fos_elastica.object_persister.application.job');
        $this->em = $this->container->get('doctrine')->getEntityManager(); //maybe move this to postUpdate function so it can be used for all
    }

    /**
     * @param \Doctrine\ORM\Event\LifecycleEventArgs $eventArgs
     */
    public function postUpdate(LifecycleEventArgs $eventArgs)
    {
        /** @var $entity Story */
        $entity = $eventArgs->getEntity();

        if ($entity instanceof $this->objectClass) {
            if ($this->isObjectIndexable($entity)) {
                $this->objectPersister->replaceOne($entity);
                $this->initialiseJob();
                foreach ($entity->getJobOpenings() as $job) {
                    $this->objectPersisterJob->replaceOne($job);
                }
            } else {
                $this->scheduleForRemoval($entity, $eventArgs->getEntityManager());
                $this->removeIfScheduled($entity);
            }
        }
    }

    public function preRemove(\Doctrine\Common\EventArgs $eventArgs)
    {
        $entity = $eventArgs->getEntity();

        if ($entity instanceof $this->objectClass) {

            $this->scheduleForDeletion($entity);
            $this->initialiseJob();
            foreach ($entity->getJobOpenings() as $job) {
                $this->objectPersisterJob->replaceOne($job);
            }
        }
    }


}

および以下のように定義されたサービス

fos_elastica.listener.application.company:
    class: 'xxx\RMSBundle\EventListener\CompanyListener'
    arguments:
        - '@fos_elastica.object_persister.application.company'
        - 'xxx\RMSBundle\Entity\Company'
        - ['postPersist', 'postUpdate', 'postRemove', 'preRemove']
        - id
    calls:
        - [ setContainer, [ '@service_container' ] ]
    tags:
        - { name: 'doctrine.event_subscriber' }

これにより、両方のインデックスが更新されます:-)

于 2014-02-21T14:05:47.240 に答える
4

私は FosElastica 3.1.0 を使用しており、Julien Rm が提供するソリューションを試しましたが成功しませんでした :-(

何日もの研究の後、私は最終的に ここで解決策を見つけました

$persister = $this->get('fos_elastica.object_persister.jaiuneidee.post');
$persister->insertOne($post);

この助けを願っています!

于 2015-10-23T13:26:51.230 に答える
3

すべてのコメントと私の調査により、fosElastica を使用して自動インデックス子オブジェクトの一般的な Gist を作成しました。

https://gist.github.com/Nightbr/ddb586394d95877dde8ed7445c51d973

実際、FOSElastica のデフォルトのリスナーをオーバーライドし、function updateRelations($entity). にリンクされているすべての関係を検索し$entity、ES にインデックスが作成されている場合 (ES タイプが存在する場合)、関連ドキュメントを更新します。

誰かがそれを見て改善したいなら、それは素晴らしいことです! ^^

前もって感謝します

于 2016-07-12T15:53:49.220 に答える
1

私は Symphony 3 と FOSElasticaBundle 3.2 を使用していますが、やり方が少し異なります。他の回答で提供されたコードを確認した後、これは非常に役立ちましたが、デフォルトのリスナーを拡張しないことにしました。代わりに、独自のリスナーを追加しただけです。

複数の (1 対多の)投稿(3)を持つことができる複数の (多対多の)サブジェクト(2) を持つことができるいくつかのカテゴリ(1) があります。投稿は、Elasticsearch に保存されるエンティティであり、それぞれの件名と独自のカテゴリに関する情報が含まれています。

そのようです:

fos_elastica:
  #...
  indexes:
    my_index:
      #...
      types:
        post: # (3)
          mappings:
            field_one: ~
            # ... Other fields
            subject: # (2)
              type: "object"
              properties:
                subject_field_one: ~
                # ... Other fields
                categories: # (1)
                  type: "nested"
                  properties:
                    category_field_one: ~
                    # ... Other fields

サービス定義 (app/config/services.yml)

services:
  # ...
  app.update_elastica_post.listener:
    class: AppBundle\EventListener\UpdateElasticaPostListener
    arguments: ['@service_container']
    tags:
      - { name: doctrine.event_listener, event: postUpdate }

そしてリスナー AppBundle\EventListener\UpdateElasticaPostListener.php

namespace AppBundle\EventListener;

use Doctrine\ORM\Event\LifecycleEventArgs;
use Symfony\Component\DependencyInjection\ContainerInterface;

use AppBundle\Entity\Category;
use AppBundle\Entity\Subject;

class UpdateElasticaPostListener
{
    private $container;
    private $objectPersisterPost;

    public function __construct(ContainerInterface $container)
    {
        $this->container = $container;
        $this->objectPersisterPost = null;
    }

    /**
     * @param \Doctrine\ORM\Event\LifecycleEventArgs $eventArgs
     */
    public function postUpdate(LifecycleEventArgs $eventArgs)
    {
        $this->checkAndUpdate($eventArgs);
    }

    protected function checkAndUpdate(LifecycleEventArgs $eventArgs)
    {
        $entity = $eventArgs->getEntity();

        if ($entity instanceof Category) {
            foreach ($entity->getSubjects() as $subject) {
                $this->updateSubjectPosts($subject);
            }
        } elseif ($entity instanceof Subject) {
            $this->updateSubjectPosts($entity);
        }
    }

    protected function updateSubjectPosts(Subject $subject)
    {
        $this->initPostPersister();
        foreach ($subject->getPosts() as $post) {
            $this->objectPersisterPost->replaceOne($post);
        }
    }

    protected function initPostPersister()
    {
        if (null === $this->objectPersisterPost) {
            // fos_elastica.object_persister.<index_name>.<type_name>
            $this->objectPersisterPost = $this->container->get('fos_elastica.object_persister.my_index.post');
        }
    }
}

以上です!remove イベントでは試していませんが、考えてみると、この解決策は最善の解決策ではないかもしれません...しかし、おそらく...

上記の@Ben Stintonと@maerckyに感謝します。

それが役立つことを願っています!(これは私の最初の回答なので、失敗しなかったことを願っています)

于 2016-04-29T10:31:04.173 に答える