2016-08-31 5 views
2

По FOSElasticaBundle documentation можно настроить приложение для использования пользовательских запросов метод строитель так:FOSElasticaBundle: Можно ли изменить «query_builder_method» в контроллере?

user: 
    persistence: 
     elastica_to_model_transformer: 
      query_builder_method: createSearchQueryBuilder 

Но можно выбрать метод QB живой, например в действии контроллера?

Я хотел бы иметь возможность контролировать то, что извлекается из БД, при преобразовании результатов Elastica в объекты Doctrine. Например. иногда я хочу сделать fetch fetch для некоторых отношений, но не могу сделать это по умолчанию.

ответ

0

Поскольку документация FOSElasticaBundle не очень точная, я просмотрел ее код и не смог контролировать, какой конструктор запросов используется на уровне контроллера.

Можно изменить весь elastica_to_model_transformer на персонализированную службу, но все же она статически определена в конфигурации. Может быть, с каким-то грязным решением это будет возможно, но я не думаю, что это того стоит.

Я решил не использовать эту функцию FOSElasticaBundle. Основная проблема, с которой я столкнулся, заключалась в том, что при использовании fos_elastica.index вместо fos_elastica.finder или репозитория для эластичных (для получения простых результатов нет Elastica\Resultset) нет метода findPaginated с возвратом Pagerfanta объект-указатель, что очень полезно в моем случае.

К счастью, хотя это не указано в документации, возможно также создать 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. Поэтому вы можете уйти в отставку при извлечении данных из Doctrine, если у вас есть все необходимые данные в ElasticSearch (если они, конечно, являются данными только для чтения). Это позволяет оптимизировать производительность вашего приложения, но уменьшая количество SQL-запросов.

Код, указанный выше, может быть обернут каким-то обслуживанием, чтобы предотвратить беспорядок в контроллерах.