简体   繁体   English

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

[英]Using Bookshelf to execute a query on Postgres JSONB array elements

I have a postgres table with jsonb array elements and I'm trying to do sql queries to extract the matching elements. 我有一个带有jsonb数组元素的postgres表,我正在尝试执行sql查询以提取匹配的元素。 I have the raw SQL query running from the postgres command line interface: 我有从postgres命令行界面运行的原始SQL查询:

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

This returns the results I'm looking for (all records from the movies table where the director jsonb elements contain any of the elements in the input element). 这将返回我正在寻找的结果(movies表中的所有记录,导演jsonb元素包含input元素中的任何元素)。

In the code, the value for ['70, '45'] would be a dynamic variable ie. 在代码中,['70,'45']的值将是一个动态变量,即。 fixArr and the length of the array is unknown. fixArr和数组的长度未知。

I'm trying to build this into my Bookshelf code but haven't been able to find any examples that address the complexity of the use case. 我正在尝试将其构建到我的书架代码中,但未能找到解决用例复杂性的任何示例。 I've tried the following approaches but none of them work: 我已经尝试了以下方法,但是它们都不起作用:

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

Can anyone help with this? 有人能帮忙吗?

As you have noticed, knex nor bookshelf doesn't bring any support for making jsonb queries easier. 如您knexknexbookshelf并没有为简化jsonb查询提供任何支持。 As far as I know the only knex based ORM that supports jsonb queries etc. nicely is Objection.js 据我所知,唯一支持jsonb查询等的基于knex的ORM是Objection.js。

In your case I suppose better operator to find if jsonb column contains any of the given values would be ?| 在您的情况下,我想更好的运算符来查找jsonb列是否包含任何给定值将为?| , so query would be like: ,因此查询如下:

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

More info how to deal with jsonb queries and indexing with knex can be found here https://www.vincit.fi/en/blog/objection-js-postgresql-power-json-queries/ 有关如何处理jsonb查询和使用knex进行索引的更多信息,请参见https://www.vincit.fi/zh/blog/objection-js-postgresql-power-json-queries/

No, you're just running into the limitations of that particular query builder and ORM. 不,您只是在遇到特定查询构建器和ORM的限制。

The easiest way is using bookshelf.Model.query and knex.raw ( whereRaw , etc.). 最简单的方法是使用bookshelf.Model.queryknex.rawwhereRaw等)。 Alias with AS and subclass your Bookshelf model to add these aliased attributes if you care about such things. 具有AS别名,并且如果要考虑此类事情,可以将Bookshelf模型子类化以添加这些别名属性。

If you want things to look clean and abstracted through Bookshelf, you'll just need to denormalize the JSONB into flat tables. 如果您希望东西看起来很干净并且可以通过书架进行抽象,则只需将JSONB规范化为平面表即可。 This might be the best approach if your JSONB is mostly flat and simple. 如果您的JSONB大多扁平而简单,这可能是最好的方法。

If you end up using lots of JSONB (it can be quite performant with appropriate indexes) then Bookshelf ORM is wasted effort. 如果你最终使用大量JSONB的(它可以与合适的索引相当高性能的),那么书架ORM是无用功。 The knex query builder is only not a waste of time insofar as it handles escaping, quoting, etc. knex查询构建器仅在处理转义,引用等方面不浪费时间。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM