Postgres operators for JSON data type using Rails 4

妖精的绣舞 提交于 2019-12-13 00:38:54

问题


Got a record:

2.1.1 :202 > r.column_data
=> {"data1"=>[1, 2, 3], "data2"=>"data2-3", "array"=>[{"hello"=>1}, {"hi"=>2}], "nest"=>{"nest1"=>"yes"}} 

Trying to query inside the array object within data1

2.1.1 :203 > Record.where("column_data -> 'data1' -> 2 = '3' ")
Record Load (0.8ms)  SELECT "records".* FROM "records" WHERE (column_data -> 'data1' -> 2 = '3' )
PG::UndefinedFunction: ERROR:  operator does not exist: json = unknown
LINE 1: ...* FROM "records"  WHERE (column_data -> 'data1' -> 2 = '3' )
                                                            ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT "records".* FROM "records"  WHERE (column_data -> 'data1' -> 2 = '3' )
ActiveRecord::StatementInvalid: PG::UndefinedFunction: ERROR:  operator does not exist: json = unknown
LINE 1: ...* FROM "records"  WHERE (column_data -> 'data1' -> 2 = '3' )
                                                            ^
HINT:  No operator matches the given name and argument type(s). You might need to add explicit type casts.
: SELECT "records".* FROM "records"  WHERE (column_data -> 'data1' -> 2 = '3' )
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/rack-mini-profiler-0.9.1/lib/patches/sql_patches.rb:160:in `exec'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/rack-mini-profiler-0.9.1/lib/patches/sql_patches.rb:160:in `async_exec'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:791:in `exec_no_cache'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:138:in `block in exec_query'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/abstract_adapter.rb:442:in `block in log'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activesupport-4.0.4/lib/active_support/notifications/instrumenter.rb:20:in `instrument'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/abstract_adapter.rb:437:in `log'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql/database_statements.rb:137:in `exec_query'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/postgresql_adapter.rb:908:in `select'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/abstract/database_statements.rb:32:in `select_all'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/connection_adapters/abstract/query_cache.rb:63:in `select_all'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/querying.rb:36:in `find_by_sql'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/relation.rb:585:in `exec_queries'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/relation.rb:471:in `load'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/relation.rb:220:in `to_a'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/activerecord-4.0.4/lib/active_record/relation.rb:573:in `inspect'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/railties-4.0.4/lib/rails/commands/console.rb:90:in `start'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/railties-4.0.4/lib/rails/commands/console.rb:9:in `start'
from /Users/mmahalwy/.rvm/gems/ruby-2.1.1/gems/railties-4.0.4/lib/rails/commands.rb:62:in `<top (required)>'
from bin/rails:4:in `require'
from bin/rails:4:in `<main>'2.1.1 :204 >

Been struggling with this for quite some time now and no clue how to get it working! Any help would be appreciated please!!


回答1:


This response requires Postgres 9.4 In your example data structure you have the following:

2.1.1 :202 > r.column_data
=> {"data1"=>[1, 2, 3], "data2"=>"data2-3", "array"=>[{"hello"=>1}, {"hi"=>2}]}

Unfortunately, checking for the existence of an element in an array only works (to my knowledge) with string values. If we had the following data, we could query it without issue.

{"data1"=>['1', '2', '3'], "data2"=>"data2-3"}

Let's test this out. Note: payload is jsonb. It will not work as a json field.

Dynamic.create(payload: {"data1"=>['1', '2', '3'], "data2"=>"data2-3"})
Dynamic.where("payload -> 'data1' ? '1'").first
=> #<Dynamic id: 8, payload: {"data1"=>["1", "2", "3"], "data2"=>"data2-3"}, created_at: "2014-12-24 02:30:31", updated_at: "2014-12-24 02:30:31">

To find out more, you can check out this article



来源:https://stackoverflow.com/questions/23098466/postgres-operators-for-json-data-type-using-rails-4

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!