【问题标题】:Querying JSONB field on a associated model with Sequelize.js and PostgreSQL使用 Sequelize.js 和 PostgreSQL 在关联模型上查询 JSONB 字段
【发布时间】:2018-03-07 08:36:23
【问题描述】:

我有两个模型 FooBarFoo 有一个字段 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()

【问题讨论】:

    标签: node.js postgresql typescript sequelize.js


    【解决方案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] 的情况下,它没有帮助。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多