FOSElasticaBundle:是否可以更改" query_builder_method"在控制器?

时间:2016-08-31 13:29:51

标签: php symfony elastica foselasticabundle

根据FOSElasticaBundle documentation,可以将应用程序配置为使用自定义查询构建器方法,如下所示:

user:
   persistence:
       elastica_to_model_transformer:
           query_builder_method: createSearchQueryBuilder

但是可以选择QB方法 live ,例如在控制器动作?

我希望能够在将Elastica结果转换为Doctrine实体的同时控制从DB中获取的内容。例如。有时我会想对某些关系进行急切的获取,但默认情况下不能这样做。

1 个答案:

答案 0 :(得分:1)

由于FOSElasticaBundle文档不是很精确,我查看了代码并发现无法控制在控制器级别使用的查询构建器。

可以将整个elastica_to_model_transformer更改为自定义服务,但仍然可以在配置中静态定义。也许有一些肮脏的解决方案可能会这样,但我不认为这是值得的。

我决定不使用FOSElasticaBundle的这个功能。我遇到的主要问题是当你使用fos_elastica.index而不是fos_elastica.finder或elastica存储库时(为了得到简单的未转换结果Elastica\Resultset),没有findPaginated方法返回Pagerfanta paginator对象,这在我的情况下非常有用。

幸运的是,虽然在文档中没有提到它,但也可以用这种方式创建Pagerfanta,但手动更多。

以下是代码段:

//generate ElaticaQuery somehow.
$browseQuery = $browseData->getBrowseQuery(); 

$search = $this->container->get('fos_elastica.index.indexName.typName');
//create pagerfanta's adapter manually
$adapter = new \Pagerfanta\Adapter\ElasticaAdapterElasticaAdapter($search, $browseQuery);
// now you can create the paginator too.
$pager = new Pagerfanta($adapter);

//do some paging work on it...
$pager->setMaxPerPage($browseData->getPerPage());
try {
    $pager->setCurrentPage($browseData->getPage());
} catch(OutOfRangeCurrentPageException $e) {
    $pager->setCurrentPage(1);
}

//and get current page results. 
/** @var Result[] $elasticaResults */
$elasticaResults = $pager->getCurrentPageResults();

// we have to grab ids manyally, but it's done the same way inside FOSElasticaBundle with previous approach
$ids = array();
foreach($elasticaResults as $elasticaResult) {
    $ids[] = $elasticaResult->getId();
}

//use regular Doctrine's repository to fetch Entities any way you want.
$entities = $this->getDoctrine()->getRepository(MyEntity::class)->findByIdentifiers($ids);

这实际上有一些优点。通常,它可以让您重新控制数据,并且不会将ElasticSearch与Doctrine联系起来。因此,如果您在ElasticSearch中拥有所有需要的数据(如果它们当然是只读数据),您可以从Doctrine中获取数据。这使您可以优化应用程序性能,同时减少SQL查询的数量。

上面的代码可以包含某种服务,以防止在控制器中弄乱。