使用FOSElastica捆绑包一次搜索多种类型

时间:2019-05-10 14:41:12

标签: php symfony elasticsearch doctrine-orm

我们有一个扩展FOS\ElasticaBundle\Repository的现有类,并且由于这个yml,它可以很好地查找页面对象:

        types:
            snapshot:
                mappings:
                    ignore_in_teaser_automatic:
                        type: boolean
                    publication_date_start:
                        type: date
                    publication_date_end:
                        type: date
                    page:
                        type: object
                        properties:
                        ...

...以及此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);

...这给了我一个很好的普通老式PHP Snapshot对象数组。好。

现在,我想从第二个对象类型-TrafficCompany添加匹配项。我添加了一些yml ...

            traffic_company:
                properties:
                    name: ~
                    description: ~
                persistence:
                    driver: orm
                    model: AppBundle\Entity\TrafficCompany
                    provider: ~
                    finder: ~

...然后我相应地修改了我的PHP ...

            ...
            ->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%')
            ...

...但是我现在得到一个错误。

  

试图调用名为class的未定义方法“ addType”   “ Elastica \ Query \ MultiMatch”

我还尝试了一些变体。有没有一种简单的方法可以将我的新对象类型添加到结果中?

1 个答案:

答案 0 :(得分:1)

有一种方法可以将多种类型的结果带入一个查询中:

https://github.com/FriendsOfSymfony/FOSElasticaBundle/blob/master/doc/cookbook/multi-type-search.md

万一链接消失,这是它们使用的代码:

$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());

关键是要在控制器(或服务)中执行此操作,而不是尝试在存储库级别执行此操作。

===

编辑:进行此操作的另一种方法是执行三个查询,但使用findHybrid()返回结果和排名数据。最终,这就是我的工作:我有三个独立的存储库,每个存储库都返回findHybrid()的结果。然后在我的控制器中,我使用array_merge()和一个usort()函数合并数据并按分数对其进行排序。