问题
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