Symfony 2 FOSElasticaBundle:弹性搜索文档不会自动与实体同步:需要运行' FOS:弹性曲线:填充'

时间:2015-04-20 18:16:05

标签: symfony elasticsearch elastica foselasticabundle

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

我应该如何继续自动将弹性搜索中的文档“更新”,而不是一直运行“php app/console fos:elastica:populate”?

我的配置中有什么问题吗?

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

弹性搜索映射在这里描述:

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": {}
   }
}'

1 个答案:

答案 0 :(得分:5)

几个小时后,解决方案来自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;
    }
}

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

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

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

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