Symfony2 FOSElasticaBundle update index for all en

2019-02-04 19:26发布

I'm using FOSElasticaBundle and Doctrine in my project, and my code works for the selective index update using the Doctrine lifecycle events. The issue I come up against is if I an update a related entity separately.

For example a person may be related to a company through a manytomany relationship. If I update the company name through company entity directly, then indexes for the person related to the company will be out of date and still relate to the company's old name.

I'm a bit lost as to how to handle this, does anyone have any suggestions? Do I have to rely on a scheduled index update and cope with inaccurate index data in the mean time, or is there a way I can call an update for entities related to the entity that has been updated.

I am relying on JMSSerializer groups to establish the mappings. I appreciate this might not be the best way to do things in the longterm.

7条回答
The star\"
2楼-- · 2019-02-04 19:59

I'm using Symphony 3 and FOSElasticaBundle 3.2 and I did things a bit differently. After reviewing the code given in the other answers, which helped a lot, I've decided not to extend the default listener. Instead I let it do its thing and I just added my own listener.

I have some Categories (1) which can have multiple (many-to-many) Subjects (2) which can have multiple (one-to-many) Posts (3). The Posts are the entities being saved in Elasticsearch with infos on their respective Subject and its own Categories.

Like so:

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

The service definition (app/config/services.yml)

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

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

And that's it! I didn't try it for the remove event and now that I think about it, maybe this solution wouldn't be the best one for it... but maybe it is...

Thanks a lot to @Ben Stinton and @maercky above.

I hope it helps! (this is my first answer around here so I hope I didn't screw up)

查看更多
登录 后发表回答