使用 Sequelize.js 和 PostgreSQL 在关联模型上查询 JSONB 字段
Posted
技术标签:
【中文标题】使用 Sequelize.js 和 PostgreSQL 在关联模型上查询 JSONB 字段【英文标题】:Querying JSONB field on a associated model with Sequelize.js and PostgreSQL 【发布时间】:2018-03-07 08:36:23 【问题描述】:我有两个模型 Foo
和 Bar
。 Foo
有一个字段 barId
,因此有一个 Bar
对象与之关联。
我可以查询我所有的 Foo
对象并包含它们关联的 Bar
对象(我正在使用带有 sequelize-typescript 的 TypeScript):
Foo.findAll<Foo>(
include: [ model: Bar ]
);
Bar
对象有一个 JSONB 字段 jsonb_field
具有结构
inner_field1: 'some text', inner_field2: 'some more text'
我可以像这样查询Bar
对象并按inner_field1
过滤:
Bar.findAll<Bar>(
where: 'jsonb_field': inner_field1: 'text to find'
);
这会产生以下 SQL 查询:
SELECT ... FROM "Bar" AS "Bar"
WHERE ("Bar"."jsonb_field"#>>'inner_field1') = 'text to find'
到目前为止一切顺利。现在让我们尝试查询Foo
对象,包括Bar
对象并按inner_field1
过滤:
Foo.findAll<Foo>(
where: '$bar.jsonb_field$': inner_field1: 'text to find' ,
include: [ model: Bar ]
);
现在这会引发异常:
Error: Invalid value [object Object]
at Object.escape (project_root\node_modules\sequelize\lib\sql-string.js:50:11)
at Object.escape (project_root\node_modules\sequelize\lib\dialects\abstract\query-generator.js:917:22)
at Object.whereItemQuery (project_root\node_modules\sequelize\lib\dialects\abstract\query-generator.js:2095:41)
at _.forOwn (project_root\node_modules\sequelize\lib\dialects\abstract\query-generator.js:1937:25)
...
作为记录,我正确地包含了 Bar 对象,因为我可以按其他非 JSONB 属性进行过滤:
Foo.findAll<Foo>(
where: '$bar.number_field$': 5 ,
include: [ model: Bar ]
);
据我所知,问题在于 Sequelize 不知道 jsonb_field
的类型,因此在将对象传递给 where 查询时会引发错误。
有没有办法解决这个错误,可能使用sequelize.literal()
或sequelize.json()
?
【问题讨论】:
【参考方案1】:使用sequelize.cast
和$contains
运算符:
Foo.findAll<Foo>(
where: '$bar.jsonb_field$':
$contains: sequelize.cast(' "inner_field1": "text to find" ', 'jsonb')
,
include: [ model: Bar ]
);
或者按照您的建议使用sequelize.literal
:
Foo.findAll<Foo>(
where: '$bar.jsonb_field$':
$contains: sequelize.literal(`' "inner_field1": "text to find" '::json`)
,
include: [ model: Bar ]
);
这两种解决方案都容易受到SQL Injections 的攻击,以确保转义或删除所有可能导致问题的字符("
,'
,...)
是的,我刚刚回答了我自己的问题。不客气。
【讨论】:
如果您需要检查是否相等,它将起作用。但是,例如,在 [Op.Like] 的情况下,它没有帮助。以上是关于使用 Sequelize.js 和 PostgreSQL 在关联模型上查询 JSONB 字段的主要内容,如果未能解决你的问题,请参考以下文章