如何在Sequelize模型的JSON类型数组字段中查询匹配结果
错误原因分析
你选择的两个运算符均不符合当前场景要求:
Op.in的作用是判断字段本身的取值是否落在传入的数组范围内(比如id IN [1,2,3]这类场景),完全不适用于「字段存储的数组包含指定元素」的匹配需求Op.contains是PostgreSQL原生数组类型(DataTypes.ARRAY)的专属运算符,你当前使用JSON类型存储数组,如果使用的是MySQL、SQLite这类不支持原生数组类型的数据库,直接调用会直接报错
正确查询实现
以下针对两种最常用的数据库场景提供写法:
场景1:使用MySQL 5.7+/8.x
MySQL对JSON数组的包含查询依赖JSON_CONTAINS函数,通过Sequelize封装的原生函数调用实现:
const { Op } = require('sequelize'); // 待匹配的关键词数组,示例:["a", "c"] const targetTags = ["a", "c"]; // 构造匹配条件:要求tags包含所有传入的关键词 const whereCondition = targetTags.map(tag => sequelize.fn( 'JSON_CONTAINS', sequelize.col('tags'), sequelize.literal(`"${tag}"`) // 字符串需要包裹双引号符合JSON格式要求 ) ); const result = await MenuItem.findAll({ where: { [Op.and]: whereCondition } });
如果需求改为匹配任意一个关键词即可返回,把上述代码中的Op.and替换为Op.or即可。
安全提示:如果
targetTags的取值来自用户输入,为避免SQL注入风险,不要直接拼接字符串,建议改用参数化写法:sequelize.fn('JSON_CONTAINS', sequelize.col('tags'), sequelize.escape(tag))
场景2:使用PostgreSQL
PostgreSQL对JSON类型数组原生支持@>包含运算符,可直接用Op.contains实现:
const { Op } = require('sequelize'); const targetTags = ["a", "c"]; const result = await MenuItem.findAll({ where: { tags: { [Op.contains]: targetTags } } });
如果后续你将tags字段类型调整为DataTypes.ARRAY(DataTypes.STRING),上述代码可以直接复用。
内容的提问来源于stack exchange,提问作者Qamar Stationwala
相关产品推荐
相关产品推荐

