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

ben*_*.IT 3 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:   ~
Run Code Online (Sandbox Code Playgroud)

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;
    }


}
Run Code Online (Sandbox Code Playgroud)

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;
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器中的测试方法:

 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');


    }
Run Code Online (Sandbox Code Playgroud)

最后,我使用此查询监控elasticsearch:

curl -XGET "http://localhost:9200/foobar/_search" -d'
{
   "query": {
      "match_all": {}
   }
}'
Run Code Online (Sandbox Code Playgroud)

ben*_*.IT 5

几个小时后,解决方案来自此资源,允许您定义一个回调,如果必须在弹性搜索中索引实体,则返回该回调.

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

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:   ~
Run Code Online (Sandbox Code Playgroud)

我还在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;
    }
}
Run Code Online (Sandbox Code Playgroud)

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

curl -XPOST "http://localhost:9200/foobar/foobar_published/_search?size=300"
curl -XPOST "http://localhost:9200/foobar/foobar_draft/_search?size=300"
Run Code Online (Sandbox Code Playgroud)

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

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