You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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' },
});

关键说明

  1. 公共条件抽离:将两个分支中相同的status、newsCategories、publishedAt条件直接放在WHERE对象根节点,避免重复代码。
  2. Raw函数合并OR逻辑:通过Raw函数编写原生SQL片段,实现两种场景的OR判断:
    • 场景1:useAvailablePeriod = FALSE(不使用可用周期)
    • 场景2:useAvailablePeriod = TRUE且时间范围有效(availableFrom小于等于当前时间或为空,同时availableTo大于等于当前时间或为空)
  3. 参数化防注入:使用:now参数传递当前时间,替代原代码中直接拼接字符串的写法,避免SQL注入风险。

内容的提问来源于stack exchange,提问作者Bohdlesk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.21 18:32:37