Поиск нескольких типов одновременно с пакетом FOSElastica - PullRequest
1 голос
/ 10 мая 2019

У нас есть существующий класс, который расширяет 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-объектов.Хорошо.

Теперь я хочу добавить совпадения из второго типа объекта - 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%')
            ...

... но теперь я получаю ошибку.

Попытка вызвать неопределенный метод с именем "addType" класса "Elastica \ Query \ MultiMatch"

Я также попробовал несколько вариантов этого.Есть ли простой способ добавить мой новый тип объекта в результаты?

1 Ответ

1 голос
/ 14 мая 2019

Существует способ объединить результаты нескольких типов в один запрос:

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() для объединения данных и сортировки их по баллам.

...