Search code examples
query-buildertypeorm

Expect orWhere() to works with andWhere() instead where()


I have a query:

topics = await topicRepository.createQueryBuilder('topic')
                               .leftJoinAndSelect('topic.user', 'user', 'topic.userId = user.id')
                               .where('topic.categoryId = :id', {
                                       id: categoryId,
                                     })
                               .andWhere('topic.title like :search', { search: `%${searchKey}%`})
                               // It should take the first where
                               .orWhere('user.pseudo like :search', { search: `%${searchKey}%` })
                               .addOrderBy(filter === 'latest' ? 'topic.created_at' : 'topic.repliesCount', 'DESC')
                               .take(limit)
                               .skip(skip)
                               .getMany();

Generated SQL query is:

SELECT DISTINCT distinctAlias.topic_id as \"ids_topic_id\", distinctAlias.topic_created_at FROM (SELECT topic.id AS topic_id, topic.title AS topic_title, topic.content AS topic_content, topic.created_at AS topic_created_at, topic.views AS topic_views, topic.repliesCount AS topic_repliesCount, topic.categoryId AS topic_categoryId, topic.userId AS topic_userId, topic.surveyId AS topic_surveyId, user.id AS user_id, user.email AS user_email, user.pseudo AS user_pseudo, user.password AS user_password, user.rank AS user_rank, user.avatar AS user_avatar, user.createdAt AS user_createdAt, user.lastActivity AS user_lastActivity, user.signature AS user_signature, user.post_count AS user_post_count, user.updatedAt AS user_updatedAt FROM topic topic LEFT JOIN user user ON user.id=topic.userId AND (topic.userId = user.id) WHERE topic.categoryId = '5' AND topic.title like '%admin%' OR topic.user.pseudo like '%admin%') distinctAlias ORDER BY distinctAlias.topic_created_at DESC, topic_id ASC LIMIT 20

The problem is here:

WHERE topic.categoryId = '5' AND topic.title like '%admin%' OR topic.user.pseudo like '%admin%')

I expected :

WHERE (topic.categoryId = '5' AND topic.title like '%admin%') OR (topic.categoryId = '5' AND topic.user.pseudo like '%admin%')

I want the .orWhere being OR from .andWhere instead .where

I don't find any documentation / issue about this use case.


Solution

  • The precedence of query conditions can be controlled by using the Brackets class:

    topics = await topicRepository.createQueryBuilder('topic')
        .leftJoinAndSelect('topic.user', 'user', 'topic.userId = user.id')
        .where('topic.categoryId = :id', {
          id: categoryId,
        })
        .andWhere(new Brackets(qb => {
          qb.where('topic.title like :search', { search: `%${searchKey}%`})
          .orWhere('user.pseudo like :search', { search: `%${searchKey}%` });                                 
        }))
        .addOrderBy(filter === 'latest' ? 'topic.created_at' : 'topic.repliesCount', 'DESC')
        .take(limit)
        .skip(skip)
        .getMany();
    
    

    (edit: added period to correct syntax)