简体   繁体   中英

How to use ransack to search MySQL JSON array in Rails 5

Rails 5 now support native JSON data type in MySQL, so if I have a column data that contains an array: ["a", "b", "c"] , and I want to search if this column contains values, so basically I would like to have something like: data_json_cont: ["b"] . So can this query be built using ransack ?

Well I found quite some way to do this with Arrays(not sure about json contains for hash in mysq). First include this code in your active record model:

self.columns.select{|column| column.type == :json}.each do |column|
      ransacker "#{column.name}_json_contains".to_sym,
      args: [:parent, :ransacker_args] do |parent, args|
        query_parts = args.map do |val|
            "JSON_CONTAINS(#{column.name}, '#{val.to_json}')"
        end
        query = query_parts.join(" * ")
        Arel.sql(query)
      end

end

Then assuming you have class Shirt with column size , then you can do the following:

search = Shirt.ransack(
  c: [{
    a: {
      '0' => {
        name: 'size_json_contains',
        ransacker_args: ["L", "XL"]
      }
    },
    p: 'eq',
    v: [1]
  }]
)
search.result

It works as follows: It checks that the array stored in the json column contains all elements of the asked array, by getting the result of each json contains alone, then multiplying them all, and comparing them to arel predicate eq with 1 :) You can do the same with OR, by using bitwise OR instead of multiplication.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM