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

Sequelize(Node.js)中enum与integer字段Like搜索的类型转换方法

解决Sequelize中Enum/Integer字段使用Like操作符的类型转换问题

这个问题我之前也碰到过,本质是PostgreSQL(从错误提示能看出来你用的是PG数据库)不允许直接对enum或integer类型的字段使用like/iLike操作符,必须先把这些字段显式转换为text类型才行。下面给你两种实用的解决办法,结合你的现有代码来修改:

方法1:用Sequelize内置的cast+col函数(推荐,更安全)

这种方式符合Sequelize的ORM风格,还能自动处理参数绑定,避免SQL注入风险。首先需要引入Sequelize的相关工具:

const { Op, Sequelize, cast, col } = require('sequelize');

然后修改你的查询条件里的enum和integer字段:

  • 对于enum类型的job.status,把原来的like条件改成用Sequelize.where结合cast转换的写法
  • 对于integer类型的job.jobReferenceId,同样转成text后再用iLike

修改后的完整whereCondn如下:

const searchValue = search || '';
whereCondn = { 
  [Op.or]:[ 
    // 处理integer类型的jobReferenceId
    Sequelize.where(cast(col('job.jobReferenceId'), 'TEXT'), Op.iLike, searchValue),
    { '$job.jobTitle$': { [Op.iLike]: `%${searchValue}%` } }, 
    { '$job.experienceLevel$': { [Op.iLike]: `%${searchValue}%` } }, 
    { '$job.location$': { [Op.iLike]: `%${searchValue}%` } }, 
    // 处理enum类型的status
    Sequelize.where(cast(col('job.status'), 'TEXT'), Op.like, `%${searchValue}%`),
    { '$job->hospital.name$':{ [Op.iLike]: `%${searchValue}%` } }, 
    { '$job->grade.gradeName$':{ [Op.iLike]: `%${searchValue}%` } }, 
    { '$job->speciality.specialityName$':{ [Op.iLike]: `%${searchValue}%` } }, 
    { '$job->specialityService.serviceName$':{ [Op.iLike]: `%${searchValue}%` } } 
  ], 
  [Op.and]:[ 
    { '$job.draft$' : false }, 
    { 'doctorId' : bodyInput['doctorId'] } 
  ] 
}; 

方法2:用literal写原生SQL片段(灵活适合复杂场景)

如果你更熟悉原生PostgreSQL语法,可以直接用Sequelize.literal写类型转换的SQL:

const searchValue = search || '';
whereCondn = { 
  [Op.or]:[ 
    // integer类型转text后做iLike
    { [Op.iLike]: Sequelize.literal(`"job"."jobReferenceId"::TEXT ILIKE '${searchValue}'`) },
    { '$job.jobTitle$': { [Op.iLike]: `%${searchValue}%` } }, 
    { '$job.experienceLevel$': { [Op.iLike]: `%${searchValue}%` } }, 
    { '$job.location$': { [Op.iLike]: `%${searchValue}%` } }, 
    // enum类型转text后做like
    { [Op.like]: Sequelize.literal(`"job"."status"::TEXT LIKE '%${searchValue}%'`) },
    { '$job->hospital.name$':{ [Op.iLike]: `%${searchValue}%` } }, 
    { '$job->grade.gradeName$':{ [Op.iLike]: `%${searchValue}%` } }, 
    { '$job->speciality.specialityName$':{ [Op.iLike]: `%${searchValue}%` } }, 
    { '$job->specialityService.serviceName$':{ [Op.iLike]: `%${searchValue}%` } } 
  ], 
  [Op.and]:[ 
    { '$job.draft$' : false }, 
    { 'doctorId' : bodyInput['doctorId'] } 
  ] 
}; 

注意事项

  • 用literal的时候要小心SQL注入风险,如果你的search参数来自用户输入,最好用参数绑定的方式:
    // 示例:绑定参数避免注入
    { [Op.like]: Sequelize.literal(`"job"."status"::TEXT LIKE '%' || :searchVal || '%'`) }
    // 然后在查询的options里加上replacements:
    replacements: { searchVal: searchValue }
    
  • 两种方法选哪种都行,cast+col的方式更贴合Sequelize的最佳实践,推荐优先使用。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 10:04:15