3

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

我应该如何继续在 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": {}
   }
}'
4

1 回答 1

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:   ~

而且我还在 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: ~}'.

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

于 2015-04-21T09:56:38.110 回答