web-dev-qa-db-fra.com

Type de données JSON Postgres Rails query

J'utilise le type de données json de Postgres mais je souhaite effectuer une requête/commande avec des données imbriquées dans le json.

Je veux commander ou interroger avec .where sur le type de données json. Par exemple, je souhaite interroger les utilisateurs qui ont un nombre d'abonnés> 500 ou je souhaite commander par abonné ou par nombre suivant.

Merci!

Exemple:

model User

data: {
     "photos"=>[
       {"type"=>"facebook", "type_id"=>"facebook", "type_name"=>"Facebook", "url"=>"facebook.com"}
      ], 
     "social_profiles"=>[
         {"type"=>"vimeo", "type_id"=>"vimeo", "type_name"=>"Vimeo", "url"=>"http://vimeo.com/", "username"=>"v", "id"=>"1"},
         {"bio"=>"I am not a person, but a series of plants", "followers"=>1500, "following"=>240, "type"=>"Twitter", "type_id"=>"Twitter", "type_name"=>"Twitter", "url"=>"http://www.Twitter.com/", "username"=>"123", "id"=>"123"}
     ]
}
48

Pour tous ceux qui trébuchent là-dessus. J'ai trouvé une liste de requêtes utilisant ActiveRecord et le type de données JSON de Postgres. N'hésitez pas à le modifier pour le rendre plus clair.

Postgres important Rails commandes:

# Sort based on the Hstore data:
2.1.1 :022 > Post.order("data->'hello' DESC")

=> #<ActiveRecord::Relation [#<Post id: 4, created_at: "2014-04-16 01:05:49", updated_at: "2014-04-16 01:05:49", data: {"hi"=>"23", "hello"=>"22"}>, #<Post id: 3, created_at: "2014-04-16 01:05:37", updated_at: "2014-04-16 01:05:37", data: {"hi"=>"13", "hello"=>"21"}>, #<Post id: 2, created_at: "2014-04-16 01:05:28", updated_at: "2014-04-16 01:05:28", data: {"hi"=>"3", "hello"=>"2"}>, #<Post id: 1, created_at: "2014-04-16 01:05:05", updated_at: "2014-04-16 01:05:05", data: {"hi"=>"2", "hello"=>"1"}>]> 



# Where inside a JSON object:
Record.where("data ->> 'likelihood' = '0.89'")

# Searching nested json object:
2.1.1 :130 > r.column_data
 => {"data1"=>[1, 2, 3], "data2"=>"data2-3", "array"=>[{"hello"=>1}, {"hi"=>2}], "nest"=>{"nest1"=>"yes"}} 

2.1.1 :130 > Record.where("column_data -> 'nest' ->> 'nest1' = 'yes' ")

# Searching within array:
Record.where("column_data #>> '{data1,1}' = '2' ")


# Searching within a value that’s an array:
Record.where("column_data #> '{array,0}' ->> 'hello' = '1' ")
# this only find for one element of the array. 

# All elements:
Record.where("column_data ->> 'array' LIKE '%hello%' ")
# This is advised against in Rails, use below:
Record.where("column_data ->> 'array' LIKE ?", "%hello%")

pdate J'écrirai un article de blog à ce sujet très prochainement et mettrai le lien ici.

125

Selon cela http://edgeguides.rubyonrails.org/active_record_postgresql.html#json il y a une différence dans l'utilisation de -> Et ->>:

# db/migrate/20131220144913_create_events.rb
create_table :events do |t|
  t.json 'payload'
end

# app/models/event.rb
class Event < ActiveRecord::Base
end

# Usage
Event.create(payload: { kind: "user_renamed", change: ["jack", "john"]})

event = Event.first
event.payload # => {"kind"=>"user_renamed", "change"=>["jack", "john"]}

## Query based on JSON document
# The -> operator returns the original JSON type (which might be an object), whereas ->> returns text
Event.where("payload->>'kind' = ?", "user_renamed")

Vous devez donc essayer Record.where("data ->> 'status' = 200 ") ou l'opérateur qui convient à votre requête ( http://www.postgresql.org/docs/current/static/functions-json.html ).

5
guapolo

Votre question ne semble pas correspondre aux données que vous avez affichées, mais si votre table est nommée users et data est un champ de cette table avec JSON comme {count:123}, puis la requête

SELECT * WHERE data->'count' > 500 FROM users

marchera. Jetez un œil à votre schéma de base de données pour vous assurer que vous comprenez la mise en page et vérifiez que la requête fonctionne avant de la compliquer avec les conventions Rails.

3
Meekohi