使用Bookshelf在Postgres JSONB数组元素上执行查询

时间:2017-09-16 21:36:59

标签: sql postgresql jsonb knex.js bookshelf.js

我有一个带有jsonb数组元素的postgres表,我正在尝试执行sql查询来提取匹配元素。我有从postgres命令行界面运行的原始SQL查询:

select * from movies where director @> any (array ['70', '45']::jsonb[])

这将返回我正在寻找的结果(导演jsonb元素包含input元素中任何元素的movies表中的所有记录)。

在代码中,['70,'45']的值将是动态变量ie。 fixArr和数组的长度未知。

我正在尝试将其构建到我的Bookshelf代码中,但未能找到解决用例复杂性的任何示例。我尝试了以下方法,但没有一种方法有效:

models.Movies.where('director', '@> any', '(array' +  JSON.stringify(fixArr) + '::jsonb[])').fetchAll()
ERROR: The operator "@> any" is not permitted

db.knex.raw('select * from movies where director @> any(array'+[JSON.stringify(fixArr)]+'::jsonb[])')
ERROR: column "45" does not exist

models.Movies.query('where', 'director', '@>', 'any (array', JSON.stringify(fixArr) + '::jsonb[])').fetchAll()
ERROR: invalid input syntax for type json

任何人都可以帮忙吗?

2 个答案:

答案 0 :(得分:0)

正如您所注意到的那样,knexbookshelf并没有为简化jsonb查询提供任何支持。据我所知,唯一支持jsonb查询的基于knex的ORM很好Objection.js

在你的情况下,我想更好的运算符来查找jsonb列是否包含任何给定值?|,所以查询将如下:

const idsAsString = ids.map(val => `'${val}'`).join(',');
db.knex.raw(`select * from movies where director \\?| array[${idsAsString}]`);

有关如何使用knex处理jsonb查询和索引的更多信息,请访问https://www.vincit.fi/en/blog/objection-js-postgresql-power-json-queries/

答案 1 :(得分:0)

不,您只是遇到了特定查询构建器和ORM的限制。

最简单的方法是使用bookshelf.Model.queryknex.rawwhereRaw等)。带有AS的别名,如果要考虑此类事情,可以将Bookshelf模型子类化以添加这些别名属性。

如果您希望东西看起来很整洁并且可以通过书架抽象,则只需将JSONB规范化为平面表即可。如果您的JSONB大多扁平而简单,这可能是最好的方法。

如果最终使用大量JSONB(可以使用适当的索引在相当中表现出色),那么书架ORM就会浪费很多精力。 knex查询构建器在处理转义,引用等方面不仅仅浪费时间。