Reputation: 1256
We have an existing class that extends FOS\ElasticaBundle\Repository
, and it does a nice job of finding page objects, thanks to this yml:
types:
snapshot:
mappings:
ignore_in_teaser_automatic:
type: boolean
publication_date_start:
type: date
publication_date_end:
type: date
page:
type: object
properties:
...
... and this PHP:
if ($limit === null) {
$limit = 1000;
}
$script = new Script('floor(_score * 100)');
$script->setLang('expression');
// Recalculate score and adjust it to apply sorting by score
$baseQuery = new Query\FunctionScore();
$baseQuery->addScriptScoreFunction($script)
->setBoostMode(Query\FunctionScore::BOOST_MODE_REPLACE);
$boolFilter = $this->getPublishBoolFilter();
if (!empty($query)) {
$matchQuery = new Query\MultiMatch();
$matchQuery->setQuery($query)
->setFields([
'_all',
'page.title^20',
])
->setType(Query\MultiMatch::TYPE_MOST_FIELDS)
->setMinimumShouldMatch('45%')
;
$boolFilter->addMust($matchQuery);
}
if (null !== $pageType) {
$this->addPageTypeFilter($boolFilter, $pageType);
}
if ($filter instanceof Collection) {
$this->addCollectionFilter($boolFilter, $filter);
}
if (is_numeric($filter)) {
$this->addYearFilter($boolFilter, $filter);
}
$this->addSiteFilter($boolFilter, $site);
$baseQuery->setQuery($boolFilter);
$query = new Query();
$query->setQuery($baseQuery);
$query->setSort(
array_merge(
['_score' => 'desc'],
$order,
self::getDefaultSortParams()
)
);
return $this->find($query, $limit, $options);
... which gives me a nice array of plain-old-php Snapshot objects. Good.
Now I want to add matches from a second object type -- TrafficCompany. I add some yml ...
traffic_company:
properties:
name: ~
description: ~
persistence:
driver: orm
model: AppBundle\Entity\TrafficCompany
provider: ~
finder: ~
... and I modify my PHP accordingly ...
...
->setType(Query\MultiMatch::TYPE_MOST_FIELDS)
->addType('traffic_company') //Does not seem to do anything useful. We still get exclusively Snapshot objects back.
->setMinimumShouldMatch('45%')
...
... but I now get an error.
Attempted to call an undefined method named "addType" of class "Elastica\Query\MultiMatch"
I've also tried a couple variations on this. Is there a simple way to add my new object type to the results?
Upvotes: 1
Views: 1031
Reputation: 1256
There's a way to bring results from multiple types into one query here:
https://github.com/FriendsOfSymfony/FOSElasticaBundle/blob/master/doc/cookbook/multi-type-search.md
In case the link dies, here's the code they use:
$query = 'search-string';
$mngr = $this->get('fos_elastica.index_manager');
$search = $mngr->getIndex('app')->createSearch();
$search->addType('article');
$search->addType('news');
$resultSet = $search->search($query);
$transformer = $this->get('fos_elastica.elastica_to_model_transformer.collection.app');
$results = $transformer->transform($resultSet->getResults());
The key is to do this in the controller (or in a service), rather than trying to do it on the repository level.
===
Edit: Another way to go about this is to do three queries but use findHybrid()
to return both the results and the ranking data. That's ultimately what I did: I have three separate repositories, each returning results from findHybrid()
. Then in my controller, I use array_merge()
and a usort()
function to merge the data and sort it by score.
Upvotes: 1