使用Rails查找空的Postgres jsob子数组

时间:2018-08-12 11:38:39

标签: ruby-on-rails postgresql ruby-on-rails-5 rails-activerecord jsonb

我在模型上有一个jsonb列,其中包含(除其他事项外)分数数组。我想找到所有分数数组为空的记录。数据如下:

Model.new(results: {scores: [], other: [], info: {things: 'stuff'}})

不幸的是,尝试查询[]会转换为搜索NULL

Model.where("results -> 'scores' = ?", []).to_sql
#=> "SELECT \"model\".* FROM \"model\" WHERE NOT (results -> 'scores' = NULL)"

我该怎么做?

1 个答案:

答案 0 :(得分:1)

ActiveRecord对PostgreSQL的更高级类型(范围,JSON等)的知识和与之的集成是不完整的,因为AR无法理解"results -> 'scores' = ?" SQL字符串,AR仅看到了(大概)包含SQL的字符串和一个占位符。因此,AR不能理解[]在替换占位符时应转换为JSON,它只是对数组执行它总是做的事情:空数组变成NULL,非空数组变成逗号分隔列表(用于in (?)构造);例如:

Model.where("results -> 'scores' = ?", []).to_sql
#=> "SELECT \"model\".* FROM \"model\" WHERE NOT (results -> 'scores' = NULL)"

Model.where("results -> 'scores' = ?", [6,11,23]).to_sql
#=> "SELECT \"model\".* FROM \"model\" WHERE NOT (results -> 'scores' = 6,11,23)"

您可以通过帮助AR进行#to_json调用,然后依靠PostgreSQL的自动类型转换来解决此问题:

Model.where("results -> 'scores' = ?", [].to_json).to_sql
#=> "SELECT \"model\".* FROM \"model\" WHERE NOT (results -> 'scores' = '[]')"

Model.where("results -> 'scores' = ?", [6,11,23].to_json).to_sql
#=> "SELECT \"model\".* FROM \"model\" WHERE NOT (results -> 'scores' = '[6,11,23]')"