Доктрина Symfony — OrderBy после запроса

Я хотел бы заказать только результат предыдущего основного запроса.

Я хочу, чтобы 10 самых просматриваемых статей были упорядочены по DESC "добавлено по дате".

Мне известны такие функции, как orderBy или даже addOrderBy, но это не то, что мне нужно, или я неправильно их реализую.

Пример получения первых 2 из 5 статей:

  • имя : а || просмотры: 100 || добавлено: 10/04/2017
  • имя : б || просмотров : 10 || добавлено: 17.04.2017
  • имя : с || просмотров : 50 || добавлено: 15.04.2017
  • имя : д || просмотров : 25 || добавлено: 04.12.2017
  • имя : е || просмотры: 200 || добавлено: 05/04/2017

Сначала я извлекаю наибольшее количество просмотров:

  1. Статья д
  2. Статья а

А затем заказал его по добавленной дате DESC (самый последний):

  1. Статья а
  2. Статья д

Мой запрос:

public function findMostViewed($limit=10, $asArray=false)
{
        $qb = $this->createQueryBuilder('n')
            ->orderBy('n.nbViews', 'DESC')
            //->addOrderBy('n.addedAt', 'DESC')
            ->getQuery()
            ->setMaxResults($limit);

        return ($asArray) ? $qb->getResult(Query::HYDRATE_ARRAY) : $qb->getResult();
}

Если бы я знал, как сделать preSelectQuery, это, вероятно, решило бы проблему...

Я подумал о SQL-запросе:

SELECT ...
FROM ...
WHERE id IN(SELECT id FROM News ORDER BY nbViews DESC LIMIT 10)
ORDER BY addedAt DESC

person Doshibu    schedule 17.04.2017    source источник


Ответы (4)


Вы можете сделать подзапрос и использовать его в своем основном запросе:

public function findMostViewed($limit=10, $asArray=false)
{
        $subqb = $this->createQueryBuilder('nn')
            ->orderBy('nn.nbViews', 'DESC')
            ->getQuery()
            ->setMaxResults($limit);

        $qb = $this->createQueryBuilder('n')
            ->where($qb->expr()->in('n.id', $subqb->getDQL())
            ->orderBy('n.addedAt', 'DESC')
            ->getQuery();

        return ($asArray) ? $qb->getResult(Query::HYDRATE_ARRAY) : $qb->getResult();
}

Обратите внимание на использование nn вместо n в подзапросе.

person Veve    schedule 18.04.2017
comment
Ваш код не сработал. Попытка вызвать неопределенный метод с именем getResult класса Doctrine\ORM\QueryBuilder. Условие «Где в» должно быть причиной. Тем не менее, я решил это сам на вашем примере и изменив условие IN. Спасибо :) - person Doshibu; 18.04.2017

Возможно, если вы используете сначала порядок «n.addedAt», а затем «n.nbViews», например:

$qb = $this->createQueryBuilder('n')
            ->orderBy('n.addedAt', 'DESC')
            ->addOrderBy('n.nbViews', 'DESC')
            ->getQuery()
            ->setMaxResults($limit);
person Israel Sanchez Lobo    schedule 18.04.2017
comment
Нет, это не то, что я хочу. При этом я получу самые последние записи, а второй orderBy даже не будет работать, если нет записи с подобным addAt. - person Doshibu; 18.04.2017

Основываясь на ответе Veve, я изменил условие WHERE IN, и мне удалось заставить его работать.

public function findMostViewed($limit=10, $asArray=false)
{
        $subqb = $this->createQueryBuilder('nn')
            ->orderBy('nn.nbViews', 'DESC')
            ->getQuery()
            ->setMaxResults($limit);

        $qb = $this->createQueryBuilder('n')
            ->where('n.id IN (:ids)')
            ->setParameter('ids', array_values($subqb->getResult()))
            ->orderBy('n.addedAt', 'DESC')
            ->getQuery();

        return ($asArray) ? $qb->getResult(Query::HYDRATE_ARRAY) : $qb->getResult();
}
person Doshibu    schedule 18.04.2017

Это тоже работа. Если вы добавите ->setFirstResult( '1' ) в код, Исраэль Родригес Санчес работает

$qb = $this->createQueryBuilder('n')
->orderBy('n.addedAt', 'DESC')
->addOrderBy('n.nbViews', 'DESC')
->getQuery()
->setFirstResult( '1' )
->setMaxResults($limit);
person pedram shabani    schedule 28.08.2018