PostgreSQL中Sequelize查询JSONB字段trader.id无结果求助
解决Sequelize查询PostgreSQL JSONB字段的问题
我来帮你搞定这个问题!之前我用Sequelize操作PostgreSQL的JSONB字段时也踩过类似的坑,你的问题主要出在查询结构不匹配、数据类型不一致以及Sequelize的JSONB查询语法使用不当这几点上,咱们一步步来修正:
首先排查两个核心错误
- 结构不匹配:你存储的
trader是一个对象{"id": 100},但第一个查询里写的是[{id: '100'}](数组),$contains会严格匹配结构,数组肯定匹配不上对象,这是第一个没结果的原因。 - 数据类型不一致:你存储的
trader.id是数字类型100,但查询时写的是字符串'100',PostgreSQL对JSONB的类型校验很严格,数字和字符串是完全不同的值,这也是查不到的关键。 - 嵌套键写法错误:直接用
'context.trader.id'作为查询键,Sequelize不会自动解析为JSONB的路径查询,得用专门的语法或者原生SQL片段。
正确的查询写法
方法一:修正$contains(或Op.contains)的用法
如果你的Sequelize版本是V4及以下,用$contains:
this.findAll({ where: { context: { $contains: { trader: { id: 100 } // 用对象而非数组,id用数字类型 } } } });
如果是V5+版本,需要导入Op操作符来使用:
const { Op } = require('sequelize'); this.findAll({ where: { context: { [Op.contains]: { trader: { id: 100 } } } } });
方法二:使用JSONB路径的原生查询(更灵活)
如果需要直接针对嵌套的id字段查询,可以用Sequelize.literal写原生SQL片段,这样更直观:
// 注意这里如果id是数字,需要转换类型(JSONB提取的默认是字符串) this.findAll({ where: Sequelize.literal(`(context->'trader'->>'id')::integer = 100`) });
如果存储的id本身就是字符串类型,就不用转换:
this.findAll({ where: Sequelize.literal(`context->'trader'->>'id' = '100'`) });
方法三:用Sequelize的JsonPath函数(版本支持的话)
如果你的Sequelize版本比较新(支持JsonPath),可以用更优雅的路径查询:
const { JsonPath } = require('sequelize'); this.findAll({ where: { [JsonPath('context', '$.trader.id')]: 100 } });
额外提醒
- 始终保证查询的数据类型和JSONB存储的类型一致,数字就是数字,字符串就是字符串,PostgreSQL不会自动转换。
- 如果不确定存储的类型,可以先在PostgreSQL里用原生SQL验证:
SELECT * FROM your_table WHERE context->'trader'->>'id' = '100';或者= 100;,看哪个能返回结果,再对应到Sequelize的写法里。
内容的提问来源于stack exchange,提问作者Arslan Pervaiz
相关产品推荐
相关产品推荐

