簡體   English   中英

Rails / Postgres查詢Hstore是否存在

[英]Rails/Postgres query Hstore for presence

我的Rails應用程序中有一些HStore列。 查看Posgresql文檔和一些博客文章 ,我發現,給定一個像這樣的哈希值的HStore值:

{ some_key: 'value' }

我可以這樣查詢列:

Model.where("the_hstore_column -> 'some_key' = 'value'")

但是,作為一個充分的查詢工具,有很多問題:

  1. 它真的只對超級簡單的值有意義。 如果值本身就是哈希或其他東西,我不知道如何有效地搜索它,如果我不知道它的所有內容。 (即使我這樣做了,我也必須將它們全部轉換為字符串化的JSON或其他東西)。

  2. 對列的內容(或列下任何鍵的內容)的存在或不存在進行查詢是沒有用的(至少,我無法提供幫助)。

換句話說(在偽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_keythe_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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM