Mysql 5.7 json datatype, query with activerecord in Rails 5
Asked Answered
T

4

11

I am making an application with Rails 5 rc1. Rails 5 support mysql 5.7 json datatype.

add_column :organizations, :external, :json

Suppose the value in this column is as follows:

+---------------------------+
| external                  |
+---------------------------+
| {"id": 10, "type": "mos"} |
+---------------------------+

To search a particular "id" and "type" in external column, I use the following query in mysql:

select external from organizations where JSON_CONTAINS(external,'{"id": 10, "type": "mos"}') ;

Now, I want to know, how to make the same query using rails. The following doesn't work:

Organization.where("JSON_CONTAINS(external,'{"id": 10, "type": "mos"}')")

Note: I cannot remove quotes around the json text as it is part of the query.

Trometer answered 18/5, 2016 at 12:59 Comment(0)
U
17

You can still leverage ActiveRecord's where method and bind variables without resorting to find_by_sql.

Organization.where("external->'$.id' = :id and external->'$.type' = :type", id: 10, type: "mos")
Uphroe answered 11/7, 2016 at 4:58 Comment(4)
This is only applicable for postgresql and not for mysql.Trometer
Works for me in Rails 5.1 and Mysql 5.7Antimere
Does not work on MariaDB 10.4, but JSON_EXTRACT() does.Stibnite
Still a valid answer with MySQL 8 and Rails 6Buttery
U
8

With MYSQL you can use JSON_EXTRACT to pull values from a JSON object stored in a field. In your case, try using...

Organization.where("JSON_EXTRACT(external, '$.id') = 10 AND JSON_EXTRACT(external, '$.type') = 'mos'")

and just for kicks, in pseudo code...

<Class>.where("JSON_EXTRACT(<column_header>, '$.<object key>') <comparison operator> <object value>")

This should get the job done, although there may be a prettier way to write it :)

Un answered 29/6, 2017 at 22:22 Comment(1)
I like this more because it works both on MySQL and MariaDB.Stibnite
P
2

Like this:

id_field = '$."id"'
type_field = '$."type"'    
Organization.where("JSON_UNQUOTE(json_extract(external, '#{id_field}')) = ? AND JSON_UNQUOTE(json_extract(external, '#{type_field}')) = ?", 10, "mos")
Phosphaturia answered 8/11, 2016 at 9:55 Comment(0)
T
0

I did not find any solution through activerecord as of now. An alternative way to query is as follows:

type = "mos"
id = 10

organization = Organization.find_by_sql(["select * from organizations where JSON_CONTAINS(external_ref ,'{\"id\": ?, \"type\": \"#{ActiveRecord::Base::sanitize(type).remove("'")}\"}')", id]).first

Once there is a solution with activerecord query interface, I will update.

Trometer answered 31/5, 2016 at 17:56 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.