[英]Rails/Postgres query Hstore for presence
我的Rails應用程序中有一些HStore列。 查看Posgresql文檔和一些博客文章 ,我發現,給定一個像這樣的哈希值的HStore值:
{ some_key: 'value' }
我可以這樣查詢列:
Model.where("the_hstore_column -> 'some_key' = 'value'")
但是,作為一個充分的查詢工具,有很多問題:
它真的只對超級簡單的值有意義。 如果值本身就是哈希或其他東西,我不知道如何有效地搜索它,如果我不知道它的所有內容。 (即使我這樣做了,我也必須將它們全部轉換為字符串化的JSON或其他東西)。
對列的內容(或列下任何鍵的內容)的存在或不存在進行查詢是沒有用的(至少,我無法提供幫助)。
換句話說(在偽sql中),我希望能夠做到這一點:
Model.where("the_hstore_column = {}")
Model.where.not("the_hstore_column = {}")
要么:
Model.where("the_hstore_column -> 'some_key' = NULL")
Model.where.not("the_hstore_column -> 'some_key' = NULL")
或者最好的是,給定HStore值{ some_key: { sub_key: 'value' } }
:
Model.where("the_hstore_column -> 'some_key' INCLUDES (?)", 'sub_key')
Model.where.not("the_hstore_column -> 'some_key' INCLUDES (?)", 'sub_key')
這些似乎不起作用,但對於我的生活,我找不到有關如何進行這些查詢的重要信息。 有誰知道如何寫它們,或者我可以在哪里尋找更好的信息?
更新在更多的環顧之后,我發現這篇文章看起來很有前景,但我無法讓代碼真正起作用。 例如Model.where("the_hstore_column ? :key", key: 'some_key')
將返回一個空的關系,即使有許多Model
與對象some_key
在the_hstore_column
。
根據Andrius Buivydas的要求 ,我正在粘貼下面模型的相關部分。 這是相對簡短的,因為我決定抽象出Hstore訪問我寫的模塊,基本上把它變成一個哈希存儲(我覺得,顯然不正確,是它的整個目的)。 我嘗試使用內置的store_accessor
,但它並不符合我的喜好,(似乎沒有幫助解析保存的哈希,現在看似明顯的原因)因此下面的ActiveRecord::MetaExt::HstoreAccessor
模塊。 ( ParsedHstore
只接受一個HStore字符串並將其解析為哈希)。
class Place.rb
include ActiveRecord::MetaExt::HstoreAccessor
hstore_accessor :hours, :extra
end
(在單獨的文件中):
module ActiveRecord
module MetaExt
module HstoreAccessor
module ClassMethods
def hstore_accessor(*symbols)
symbols.each do |field|
class_eval do
define_method(field) do
ParsedHstore.new(self[field.to_sym]).hash_value
end
define_method("add_to_#{field}!") do |arg|
self[field.to_sym] = self[field.to_sym].merge(arg)
send("#{field}_will_change!")
save
arg
end
define_method("add_to_#{field}") do |arg|
self[field.to_sym] = self[field.to_sym].merge(arg)
send("#{field}_will_change!")
arg
end
define_method("remove_from_#{field}") do |arg|
other = self[field].dup
other.delete(arg.to_s); other.delete(arg.to_sym)
self[field.to_sym] = other
send("#{field}_will_change!")
self[field.to_sym]
end
define_method("remove_from_#{field}!") do |arg|
other = self[field].dup
other.delete(arg.to_s); other.delete(arg.to_sym)
self[field.to_sym] = other
send("#{field}_will_change!")
save
self[field.to_sym]
end
define_method("set_#{field}") do |arg|
self[field.to_sym] = arg
send("#{field}_will_change!")
self[field.to_sym]
end
define_method("set_#{field}!") do |arg|
self[field.to_sym] = arg
send("#{field}_will_change!")
self[field.to_sym]
end
end
end
end
end
def self.included(base)
base.extend ClassMethods
end
end
end
end
這個想法是,這讓我可以輕松地向HStore字段添加/刪除值,而無需考慮合並和_will_change!
邏輯每一次。 所以我可以這樣做,例如: Place.first.add_to_extra({ key: 'value'})
。
我應該制作這些字段
json
還是jsonb
? 我覺得我在這里重新發明輪子,或者更恰當地說,試圖將馬變成輪子或其他東西。
另外,我可能誤解了查詢示例。 我確實在我的數據庫中嘗試了這個查詢(在extra
字段下有許多非空ranking
鍵的地方),並且顯示為空關系:
Place.where("extra ? :key", key: 'ranking')
如果我把這個語法搞砸了,我不會感到驚訝,因為它看起來很奇怪。 那會不會取代
?
使用'ranking'
,將查詢轉換為這個?:Place.where("extra ranking :key")
? 看起來很奇怪,並且與我運行的任何其他SQL強烈不同。 或者它轉向Place.where("extra ? ranking")
? 但是?
通常用於安全注入變量,不是嗎?
如果我的模型或其他地方的其他內容更具相關性,請告訴我。
它真的只對超級簡單的值有意義。 如果值本身就是哈希或其他東西,我不知道如何有效地搜索它,如果我不知道它的所有內容。
Postgresql HStore僅存儲兩個字符串的鍵值對。 因此,您不能存儲散列,零或其他類似對象的東西 - 它們將被轉換為字符串。
Model.where(“the_hstore_column?:key”,key:'some_key')
如果一切都正確定義,這應該工作。 您可以使用hstore列值的定義粘貼模型文件的摘錄嗎?
查找空hstore列的另一種方法是
Model.where(hstore_column: ['',nil])
要么
Model.where("hstore_column='' OR hstore_column IS NULL")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.