Typeorm Find Options中简化Where条件Or逻辑(不使用Query Builder)
简化TypeORM findAndCount的WHERE OR逻辑(不使用Query Builder)
问题描述
我在使用TypeORM的findAndCount方法编写查询时,WHERE条件通过数组多元素实现OR逻辑,导致整体结构过于庞大。想请教能否不使用Query Builder,通过类似availableFrom/availableTo的写法来简化OR逻辑,减少WHERE数组的元素数量?
原查询代码如下:
await this.newsRepository.findAndCount({ select: { id: true, publishedAt: true, isDisplayed: true, priority: true, availableTo: true, availableFrom: true, useAvailablePeriod: true, }, where: [ { status: NewsStatus.PUBLISHED, newsCategories: { seoName: params.categorySeoName }, useAvailablePeriod: true, availableFrom: `< ${new Date()} OR IS NULL`, availableTo: `> ${new Date()} OR IS NULL`, publishedAt: LessThanOrEqual(new Date()), }, { status: NewsStatus.PUBLISHED, newsCategories: { seoName: params.categorySeoName }, useAvailablePeriod: false, publishedAt: LessThanOrEqual(new Date()), }, ], order: { publishedAt: 'DESC', priority: 'DESC' }, });
解决方案
完全可以通过TypeORM的Raw函数将两个分支的OR逻辑合并到单个WHERE对象中,同时抽取出公共条件,大幅精简代码结构,且无需使用Query Builder。
修改后的代码:
import { Raw, LessThanOrEqual } from "typeorm"; await this.newsRepository.findAndCount({ select: { id: true, publishedAt: true, isDisplayed: true, priority: true, availableTo: true, availableFrom: true, useAvailablePeriod: true, }, where: { status: NewsStatus.PUBLISHED, newsCategories: { seoName: params.categorySeoName }, publishedAt: LessThanOrEqual(new Date()), // 合并OR逻辑:要么不使用可用周期,要么使用且时间条件满足 useAvailablePeriod: Raw( (alias) => `${alias} = FALSE OR (${alias} = TRUE AND (availableFrom <= :now OR availableFrom IS NULL) AND (availableTo >= :now OR availableTo IS NULL))`, { now: new Date() } ), }, order: { publishedAt: 'DESC', priority: 'DESC' }, });
关键说明
- 公共条件抽离:将两个分支中相同的
status、newsCategories、publishedAt条件直接放在WHERE对象根节点,避免重复代码。 - Raw函数合并OR逻辑:通过
Raw函数编写原生SQL片段,实现两种场景的OR判断:- 场景1:
useAvailablePeriod = FALSE(不使用可用周期) - 场景2:
useAvailablePeriod = TRUE且时间范围有效(availableFrom小于等于当前时间或为空,同时availableTo大于等于当前时间或为空)
- 场景1:
- 参数化防注入:使用
:now参数传递当前时间,替代原代码中直接拼接字符串的写法,避免SQL注入风险。
内容的提问来源于stack exchange,提问作者Bohdlesk
相关产品推荐
相关产品推荐

