2016-03-02 87 views
1

我的產品模型有一個jsonb字段specs(我們使用ActiveRecord的store_accessor管理)。我的許多產品的規格都有一個稱爲spec_options的哈希規格。帶jsonb數組的rails(postgres)查詢

在此之前,此spec_option字段只是文本。現在它需要是一個數組。

之前,現在用於查詢產品此字段的範圍是這樣的:

scope :with_spec_options, ->(spec_options) { 
    where("'#{spec_options}'::jsonb \? (specs->>'spec_option')") 
} 

紅寶石當量(只是爲了幫助理解這是什麼做的):

select{ |product| spec_options.include?(product.specs['spec_option']) } 

的ActiveRecord當量(如果spec_option是一個普通的列):

where(spec_option: spec_options) 

但是,現在這specs['spec_options']是一個數組,我不能那樣做。我想我需要使用postgres'?| jsonb操作符,但是我無法弄清楚如何將這個操作的右側轉換爲正確的格式。

紅寶石相當於:

def self.with_spec_options(spec_options) 
    all.select{|product| 
     if product.specs['spec_options'].present? 
      product.specs['spec_options'].any?{|option| 
       spec_options.include?(option) 
      } 
     else 
      false 
     end 
    } 
end 

任何人有想法?

回答

6

你想要使用的是@> operator,它測試你的左手值是否包含右手的值。 「包含」作品對象和數組,因此下面的查詢將工作:

SELECT * FROM products WHERE specs->'spec_options' @> '["spec1", "spec2"]'; 

這點我相信你可以變身爲ActiveRecord的兼容語法像這樣:

scope :with_spec_options, ->(spec_options) { 
    where("specs->'spec_option' @> ?", spec_options.to_json) 
} 
+1

謝謝!那幾乎就是這樣。操作的雙方都需要是jsonb,所以這工作: 'where(「specs - >'spec_option'@>?:: jsonb」,spec_options.to_json)' – Obversity

+0

廢棄,你不需要額外的:: jsonb轉換: 'where(「specs - >'spec_option'@>?」,spec_options.to_json)' – Obversity

+0

呃,所以我認爲這是一個解決方案,但它不是*完全*我需要的。如果查詢的選項中有_any_匹配,它需要返回結果。此答案僅返回_all_匹配的結果。 – Obversity