1 Отредактировано guyasyou (2015-04-16 12:09:19)

Тема: queryBulder барахлит

Здравствуйте!
Работаю с Concrete5, там стоит Doctrine 2, использую его для работы с БД.

Вот какая странная штука появилась:
в queryBulder ввожу такие данные

//Это костяк запроса в модели ProductList
$this->query->select('pr.prID')
            ->from('EasyShopProducts', 'pr')
            ->leftJoin('pr', 'EasyShopProductSearchIndexAttributes', 'prIndex', 'pr.prID = prIndex.prID')
            ->leftJoin('pr', 'EasyShopProductStatsIndexed', 'prStatsIndex', 'pr.prID = prStatsIndex.prID');
 
//Потом подключается сортировка с присоединением таблицы со статистикой
$this->query
            ->select('pr.prID, count(DISTINCT `action`) as viewedCount')
            ->leftJoin('pr', 'EasyShopProductStats', 'prStats', 'pr.prID = prStats.prID')
            ->andWhere('prStats.action = :actionType')
            ->setParameter('actionType', 'viewed')
            ->add('groupBy', 'pr.prID');
        $this->sortBy('viewedCount', 'DESC');

Суть запроса, отсортировать товары по количеству просмотров, а в БД каждый просмотр отдельной строкой.
Этот запрос работал, но недавно, случайно заметил что он сломался.

Вот что выдает Doctrine на выходе теперь:

SELECT count(DISTINCT pr.prID) FROM EasyShopProducts pr LEFT JOIN EasyShopProductSearchIndexAttributes prIndex ON pr.prID = prIndex.prID LEFT JOIN EasyShopProductStatsIndexed prStatsIndex ON pr.prID = prStatsIndex.prID LEFT JOIN EasyShopProductStats prStats ON pr.prID = prStats.prID WHERE (pr.isActive = 1) AND (prStats.action = "viewed") GROUP BY pr.prID ORDER BY viewedCount DESC LIMIT 1

Обратите внимание на SELECT, он не соответствует введенному в конструктор.

Если из конструктора убрать count(DISTINCT `action`) as viewedCount, то SELECT строится соответствующий.

Что не так?

2

Re: queryBulder барахлит

guyasyou пишет:

Что не так?


guyasyou пишет:

->select('pr.prID, count(DISTINCT `action`) as viewedCount')

Попробуйте таки разделить в селекте запрашиваемые поля, судя по всему Доктрина ваше перечисление нормально понимать не хочет. Т.е. что-то вроде ->select(['pr.prID', 'COUNT(DISTINCT `action`) as viewedCount']).
Еще Доктрина не всегда нормально понимает вычурные запросы (функции и процедуры в select), но в данном случае я ничего нестандартного не вижу.

3 Отредактировано guyasyou (2015-04-16 14:59:42)

Re: queryBulder барахлит

А я пробовал разделять, та же фигня.

Что интересно, когда только слепил запрос, он работал.
Но потом много что менялось, но вроде в классе поиска я не очень то копался.

А есть какая-либо альтернатива решения задачи?

4

Re: queryBulder барахлит

guyasyou пишет:

А есть какая-либо альтернатива решения задачи?

Без наличия структуры в базе сложно гадать, голова после 2-х дневного дедлайна отказывается виртуализировать запрос. default/smile
На сколько я могу судить, это уже DQL-ный QueryBulder, не ORM.
Можно конечно написать на чистом SQL и скормить это Доктриновскому коннекшену (тем более что у вас результат — массив скаляров, а не объекты), но это некрасивый хак, по хорошему нужно разобраться с тем, что именно Доктрина не понимает или не может в текущем запросе.

5 Отредактировано guyasyou (2015-04-16 15:47:23)

Re: queryBulder барахлит

В коннектор идут 2 запроса, отличаются только SELECT-ом, первый верный, второй кривой.

Нашел вот что, видать он генерит второй - неверный:

protected function createPaginationObject() {
        $adapter = new DoctrineDbalAdapter($this->deliverQueryObject(), function ($query) {
            $query->select('count(distinct pr.prID)')->setMaxResults(1);
        });
        $pagination = new Pagination($this, $adapter);
        return $pagination;
    }

Видать отсюда и вылазит тот неверный SELECT
что он делает?

6

Re: queryBulder барахлит

guyasyou пишет:

что он делает?

На сколько можно судить — модифицирует запрос для получения общего количество записей в выборке для построения пагинации. И да, результирующий запрос, который вы показали в посте, полностью соответствует его модификациям. Вот только (как минимум по задумке), он должен делать это с клоном запроса, поскольку запрос количества записей — это отдельный запрос к БД, и к основному запросу, в котором возвращаются данные, никак не относится.

А у вас кроме этого запроса второй, нормальный, не генерируется?

7

Re: queryBulder барахлит

Я написал выше.
Запросов 2, нормальный и кривой.
Ставить условие в функцию и втыкать дополнение к селектору если он нужен?

8

Re: queryBulder барахлит

guyasyou пишет:

Я написал выше.

Спишем на усталость. Внимательно читать уже лень и некогда. default/smile

guyasyou пишет:

Ставить условие в функцию и втыкать дополнение к селектору если он нужен?

Поскольку я понятия не имею, при каких условиях и чем в вашем коде вызывается метод createPaginationObject(), то могу ответить только общими словами — да, поставить где-нибудь условие (в нем самом или там, где он вызывается), если этот метод срабатывает на те запросы, на которые не должен, и которым пагинация не нужна. Лишние запросы — зло.

9

Re: queryBulder барахлит

В том то и дело, что пагтнатция нужна.
Спаибо за помощь, пойду ставить костыль((