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

如何在TypeORM中使用findOptions实现AND与OR组合查询?

需求与问题

目标SQL

想要构建的SQL查询如下:

SELECT * FROM studies WHERE idUser = '12489184291' AND (type LIKE '%something%' OR type LIKE '%something%')

需求是在用户A的所有studies记录中,使用LIKE运算符进行非精确搜索,查找名称或类型以"study for"开头的记录,询问该需求是否可行。

当前代码实现

当前基于TypeORM的代码实现如下:

const searchQuery = getSearchQuery(search, on);
const filterQuery = getFilterQueries(filters);

req.options = {
    where: [
        ...searchQuery,
        ...filterQuery,
    ]
}

const getSearchQuery = (search: string, on: string) => {
    if (!search) return [];

    const searchQuery = `%${search}%`;

    switch (on) {
        case 'estudios':
            return [
                {
                    nombre: ILike(searchQuery)
                },
                {
                    tipoModificacion: ILike(searchQuery)
                },
                {
                    antecedentes: ILike(searchQuery)
                },
                {
                    observaciones: ILike(searchQuery)
                },
            ]
        default: return [];
    }
}

const getFilterQueries = (filters: {}) => {
    let filterObj: any = {};

    const urlFilters = new URLSearchParams(filters);

    urlFilters.forEach((value, key) => {
        if (key === 'createdAt' || key === 'responseDate') {
            filterObj = {
                ...filterObj,
                ...dateRange(key, value)
            }
            return;
        } else {
            filterObj[key] = value;
        }
    });

    if (Object.keys(filterObj).length > 0) {
        return [filterObj]
    } else {
        return [];
    }
};

当前问题:where数组写法默认是全局OR逻辑,无法实现目标SQL的AND+OR混合逻辑,因此提出两个疑问:

  1. 能否使用findOptions在同一个where中同时实现AND与OR逻辑?
  2. 还是更推荐使用QueryBuilder?

解答

需求可行性

完全可行,你的目标SQL逻辑是常规的多条件查询场景:通过AND固定用户筛选范围,再用OR组合多个模糊搜索条件,完全可以实现。

方案一:用findOptions实现混合逻辑

TypeORM的findOptions支持嵌套AND/OR操作符,无需依赖数组(数组元素默认是OR关系),通过嵌套结构就能实现需求:

修改代码如下,将搜索条件包装成OR组,再与过滤条件通过AND组合:

const searchQuery = getSearchQuery(search, on);
const filterQuery = getFilterQueries(filters);

const whereConditions: any[] = [];

// 添加过滤条件(如idUser这类全局AND条件)
if (filterQuery.length > 0) {
    whereConditions.push(...filterQuery);
}

// 添加搜索的OR条件组
if (searchQuery.length > 0) {
    whereConditions.push({
        OR: searchQuery
    });
}

req.options = {
    where: whereConditions.length > 0 ? whereConditions : undefined
};

改造后生成的SQL会自动变成:WHERE (filter条件) AND (nombre LIKE ... OR tipoModificacion LIKE ...),完美匹配你的目标逻辑。

方案二:使用QueryBuilder(推荐复杂场景)

如果后续查询逻辑会变得更复杂(比如多层嵌套条件、关联表查询、聚合函数等),QueryBuilder是更优选择,它能精准控制SQL生成,可读性和扩展性更强:

示例代码:

import { getRepository } from "typeorm";
import { Study } from "./entities/Study"; // 替换为你的实体类

// 构建查询器
const queryBuilder = getRepository(Study).createQueryBuilder('study');

// 处理过滤条件
const filterObj = getFilterQueries(filters)[0];
if (filterObj) {
    Object.keys(filterObj).forEach(key => {
        if (key === 'createdAt' || key === 'responseDate') {
            // 假设dateRange返回{ [key]: Between(start, end) }
            const { start, end } = filterObj[key];
            queryBuilder.andWhere(`study.${key} BETWEEN :start AND :end`, { start, end });
        } else {
            queryBuilder.andWhere(`study.${key} = :${key}`, { [key]: filterObj[key] });
        }
    });
}

// 处理搜索的OR条件
const search = ...; // 你的搜索输入值
if (search) {
    const searchPattern = `%${search}%`;
    queryBuilder.andWhere(`
        study.nombre ILIKE :search 
        OR study.tipoModificacion ILIKE :search 
        OR study.antecedentes ILIKE :search 
        OR study.observaciones ILIKE :search
    `, { search: searchPattern });
}

// 执行查询
const result = await queryBuilder.getMany();

总结

  • 简单场景:用findOptions的嵌套AND/OR足够满足需求,代码更简洁;
  • 复杂场景:推荐使用QueryBuilder,调试和扩展更方便。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 17:23:23