2014-03-26 93 views
30

我正在使用Postgres的json數據類型,但想要使用嵌套在json中的數據執行查詢/排序。Postgres JSON數據類型Rails查詢

我想用json數據類型的.where命令或查詢。例如,我想要查詢擁有超過500人的追隨者人數的用戶,或者想要按照追隨者或追蹤次數進行訂購。

謝謝!

例子:

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"} 
    ] 
} 
+0

PostgreSQL版本? –

+0

PostgrSQL 9.3是我正在使用的 –

+0

好,你看過像' - >'這樣的json運算符嗎? –

回答

88

對於任何絆倒這一點的人。我想出了一個使用ActiveRecord和Postgres的JSON數據類型的查詢列表。隨意編輯這個更清楚。

Postgres的重要軌道命令:

# 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%") 

更新 我很快將寫在這個博客中,並將在此處放鏈接。

+0

這裏有一個有用的答案,處理多個級別:http://stackoverflow.com/questions/23609331/how-do-i-search-over-a-json-type-of-postgres-in-multilevels-using -active-record及其背後的邏輯:http://www.postgresql.org/docs/9.3/static/functions-json.html –

+0

感謝@AmeetWadhwani我可能會寫一篇關於此主題的博客文章。敬請期待其他人通過這個答案! –

+1

@MohamedElMahallawy你能幫助這個問題:http://stackoverflow.com/questions/27697489/use-where-queries-in-jsonb-datatype-in​​-rails-postgres。我無法弄清楚哪裏有一個沒有鍵的json元素數組的查詢。 – Aravind

3

你的問題似乎並不符合您所顯示的數據,但如果你的表名爲usersdata與JSON是表像{count:123}一個字段,然後查詢

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

會工作。看看你的數據庫模式,確保你理解了佈局,並在使用Rails約定使其複雜化之前檢查查詢是否有效。

+3

這對我在Postgres 9.3.3中不起作用,除非我將JSON結果轉換爲文本然後轉換爲整數:'SELECT * FROM users WHERE(data - >'count'):: text :: integer> 500; ' – JacobEvelyn

3

根據這一http://edgeguides.rubyonrails.org/active_record_postgresql.html#json 有區別使用->->>

# 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") 

所以,你應該嘗試Record.where("data ->> 'status' = 200 ")或適合您的查詢(http://www.postgresql.org/docs/current/static/functions-json.html)操作。