Как объединить queryBuilder и необработанные запросы в таблице соединений от многих ко многим? - PullRequest
0 голосов
/ 30 апреля 2020

У меня следующий запрос

SELECT news.*, count(*) AS common_tags
FROM news
JOIN news_news_tag ON news.id = news_news_tag.news_id
WHERE news_tag_id IN 
   (SELECT news_tag_id FROM news_news_tag WHERE news_id = 2 ) 
AND news.id != 2 GROUP BY news.id ORDER BY common_tags DESC 

Чего я хочу добиться, так это получить гидратированные объекты новостей, упорядоченные по количеству общих тегов с предоставленным идентификатором новостей. News и Tag имеют отношение многие ко многим с news_news_tag таблицей соединений.

News сущность получила гораздо больше других отношений. Вот почему я не хочу создавать собственный запрос для обработки всех других отношений. Я хотел бы преобразовать вышеупомянутый запрос, чтобы использовать его с построителем запросов. Я не смог использовать DQL, потому что мой оператор where использует таблицу соединения (соединения), и мне также нужно использовать join для этой таблицы.

Всего у меня 2 проблемы :

  1. Как я могу создать подзапрос DQL, чтобы выбрать что-то из множества таблиц присоединения ко многим)? Если я знаю, что могу сделать что-то вроде: ->where($queryBuilder->expr()->in('u.id', $mySubQueryAsDQL))

  2. Как добавить это join утверждение, которое я мог бы использовать news_tag_id в where утверждении?

Если это невозможно, я думаю, что мне нужно было бы создать два двунаправленных отношения «один ко многим» и «многие к одному» вместо «многие ко многим» и работать над специальной объединяющей сущностью.

1 Ответ

0 голосов
/ 30 апреля 2020

Я наконец-то нашел следующее решение. Я решил разделить этот запрос на два отдельных. Во-первых, я могу использовать только простой необработанный запрос, так как мне нужны результаты только для оператора where. Второй запрос может быть построен с использованием построителя запросов обычным способом. Вам нужно только избавиться от дополнительного столбца count в конце.

Однако, если кто-то знает решение, как использовать мой первый необработанный запрос непосредственно в построителе запросов в качестве необработанного подзапроса для оператора where, поделитесь со мной.

public function getRelatedNews($newsId, $limit = 6)
    $connection = $this->getEntityManager()->getConnection();
    $sql = 'SELECT news_tag_id FROM news_news_tag WHERE news_id = :newsId';
    try {
        $stmt = $connection->prepare($sql);
    } catch (DBALException $e) {
        return [];
    }
    $stmt->execute(['newsId' => $newsId]);
    $newsTagId = $stmt->fetchAll();

    if (empty($newsTagId)) {
        return [];
    }

    $newsTagId = array_column($newsTagId, 'news_tag_id');

    $query = $this->createQueryBuilder('n')
        ->addSelect('COUNT(n.id) as common_tags_count')
        ->innerJoin("n.tags", "t")
        ->andWhere('t.id IN(:tagsId)')->setParameter('tagsId', array_values($newsTagId))
        ->andWhere('n.id != :newsId')->setParameter('newsId', $newsId)
        ->orderBy('common_tags_count', 'DESC')
        ->setMaxResults($limit)
        ->groupBy('n.id')
    ;

    $results = $query->getQuery()->getResult();

    $news = [];
    foreach ($results as $result) {
        $news[] = $result[0];
    }

    return $news;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...