Symfony 2 FOSElasticaBundle:弹性搜索文档不会自动与实体同步:需要 运行 'fos:elastica:populate'

Symfony 2 FOSElasticaBundle : elastic search documents are not automatically synchronized with entities : need to run ' fos:elastica:populate'

我正在使用 FOSElasticaBundle 开发名为 'Foobar' 的基本实体。 我已经定义了 1 个名为 'foobar' 的索引,有 2 种类型 'foobar_published' 和 'foobar_draft'。 问题是我的 Foobar 实体不会自动与弹性搜索同步,我需要在每次修改 Foobar 实体后 运行,以下命令:“php app/console fos:elastica:populate”。之后,我在elasticsearch中的文档就如它们应该的那样,这意味着弹性文档就像我数据库中的相关实体。

我应该如何继续在 elasticsearch 'up to date' 中自动获取我的文档而无需一直 运行ning 'php app/console fos:elastica:populate'?

我的配置有问题吗?

来自我的 composer.json 的版本信息:"friendsofsymfony/elastica-bundle": "~3.0.0"

此处描述了 elasticsearch 映射:

fos_elastica:
    clients:
        default: { host: %elasticsearch_host%, port: %elasticsearch_port% }
    indexes:
        foobar:
             client:     default
             types:
                foobar_published:
                    mappings:
                        state: ~
                        field1: ~
                    persistence:
                        driver:   orm
                        model:    App\MyBundle\Entity\Foobar
                        provider:
                            query_builder_method: createIsIndexablePublishedQueryBuilder
                        listener: {immediate: ~}
                        finder:   ~

                foobar_draft:
                    mappings:
                        state: ~
                        field1: ~
                    persistence:
                        driver:   orm
                        model:    App\MyBundle\Entity\Foobar
                        provider:
                            query_builder_method: createIsIndexableDraftQueryBuilder
                        listener: {immediate: ~}
                        finder:   ~

Foobar实体定义如下:

/**
 * @ORM\Entity(repositoryClass="App\MyBundle\Repository\FoobarRepository")
 */
class Foobar extends BaseEntity
{
    const STATE_TO_BE_INDEXED_IN_ELA = 'published';
    const STATE_DRAFT_TO_BE_INDEXED_IN_ELA = 'draft';
    const STATE_NOT_TO_BE_INDEXED_IN_ELA = 'unpublished';

    /**
     * @ORM\Column(type="string")
     */
    private $state;
    /**
     * @ORM\Column(type="string")
     */
    private $field1;

    /**
     * @return mixed
     */
    public function getState()
    {
        return $this->state;
    }

    /**
     * @param mixed $state
     */
    public function setState($state)
    {
        $this->state = $state;
    }

    /**
     * @return mixed
     */
    public function getField1()
    {
        return $this->field1;
    }

    /**
     * @param mixed $field1
     */
    public function setField1($field1)
    {
        $this->field1 = $field1;
    }


}

FoobarRepository 如下所示:

class FoobarRepository extends EntityRepository
{
    public function createIsIndexablePublishedQueryBuilder()
    {
        $qb = $this->createQueryBuilder('foobar');
        $qb
            ->where('foobar.state = :state')
            ->setParameter('state', Foobar::STATE_TO_BE_INDEXED_IN_ELA);
        return $qb;
    }


    public function createIsIndexableDraftQueryBuilder()
    {
        $qb = $this->createQueryBuilder('foobar');
        $qb
            ->where('foobar.state = :state')
            ->setParameter('state', Foobar::STATE_DRAFT_TO_BE_INDEXED_IN_ELA);
        return $qb;
    }
}

控制器中的测试方法:

 public function indexAction()
    {
        $em = $this->get("doctrine.orm.default_entity_manager");

        $foobar = new Foobar();
        $foobar->setField1('should be indexed in ela');
        $foobar->setState(Foobar::STATE_TO_BE_INDEXED_IN_ELA);

        $foobar2 = new Foobar();
        $foobar2->setField1('should NOT be indexed in ela');
        $foobar2->setState(Foobar::STATE_NOT_TO_BE_INDEXED_IN_ELA);


        $foobar3 = new Foobar();
        $foobar3->setField1('should  be indexed in ela');
        $foobar3->setState(Foobar::STATE_DRAFT_TO_BE_INDEXED_IN_ELA);

        $em->persist($foobar);
        $em->persist($foobar2);
        $em->persist($foobar3);
        $em->flush();


        $existingFoobar = $em->getRepository('AppMyBundle:Foobar')->findAll();
        foreach ($existingFoobar as $foo) {
            echo $foo->getId() . '  : ' . $foo->getField1() . '  ' . $foo->getState();
            echo '<br>';
        }


        return new Response('done');


    }

最后,我用这个查询监控 elasticsearch:

curl -XGET "http://localhost:9200/foobar/_search" -d'
{
   "query": {
      "match_all": {}
   }
}'

几个小时后,解决方案来自this ressource that allows you to define a callback that returns if an entity must be indexed in elastic search.

所以配置现在看起来像这样:

fos_elastica:
    clients:
        default: { host: %elasticsearch_host%, port: %elasticsearch_port% }
    indexes:
        foobar:
             client:     default
             types:
                foobar_published:
                    indexable_callback: 'isPublished'
                    mappings:
                        state: ~
                        field1: ~
                    persistence:
                        listener: ~
                        driver:   orm
                        model:    App\MyBundle\Entity\Foobar
                        provider:
                            query_builder_method: createIsIndexablePublishedQueryBuilder
                        finder:   ~

                foobar_draft:
                    indexable_callback: 'isDraft'
                    mappings:
                        state: ~
                        field1: ~
                    persistence:
                        listener: ~
                        driver:   orm
                        model:    App\MyBundle\Entity\Foobar
                        provider:
                            query_builder_method: createIsIndexableDraftQueryBuilder
                        finder:   ~

而且我还在 Foobar 实体中实现了回调方法:

class Foobar extends BaseEntity {
...   


    public function isPublished()
    {

        if ($this->getState() === self::STATE_TO_BE_INDEXED_IN_ELA) {
            return true;
        }
        return false;
    }


    public function isDraft()
    {

        if ($this->getState() === self::STATE_DRAFT_TO_BE_INDEXED_IN_ELA) {
            return true;
        }
        return false;
    }
}

现在一切正常 运行,文档与正确索引 ant 类型的文档同步。 我使用这些查询来检查结果:

curl -XPOST "http://localhost:9200/foobar/foobar_published/_search?size=300"
curl -XPOST "http://localhost:9200/foobar/foobar_draft/_search?size=300"

注意:我还将配置文件中的侦听器 属性 更改为 'listener: ~' 而不是 'listener: {immediate: ~}'

我测试了插入、删除和更新语句,现在一切正常!