Rails (postgres) query with jsonb array

自闭症网瘾萝莉.ら 提交于 2019-11-30 17:53:00

问题


My Product model has a jsonb field specs (which we're managing using ActiveRecord's store_accessor). Many of my products' specs have a spec in that hash called spec_options.

Before now, this spec_option field was just text. Now it needs to be an array.

The scope used before now to query products for this field was this:

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

Ruby equivalent (just to help understand what this is doing):

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

ActiveRecord equivalent (if spec_option were a regular column):

where(spec_option: spec_options)

However, now that specs['spec_options'] is an array, I can't do that. I think I need to use postgres' ?| jsonb operator, but I can't work out how to get the right side of this operation into the correct format.

Ruby equivalent:

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

Anyone got ideas?


回答1:


What you want to use is the @> operator, which tests whether your left-hand value contains the right-hand value. "Contains" works for both objects and arrays, so the following query would work:

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

Which I believe you can transform into ActiveRecord-compatible syntax like so:

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


来源:https://stackoverflow.com/questions/35737931/rails-postgres-query-with-jsonb-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!