12

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.

4 Answers 4

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")
Sign up to request clarification or add additional context in comments.

4 Comments

This is only applicable for postgresql and not for mysql.
Works for me in Rails 5.1 and Mysql 5.7
Does not work on MariaDB 10.4, but JSON_EXTRACT() does.
Still a valid answer with MySQL 8 and Rails 6
9

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 :)

1 Comment

I like this more because it works both on MySQL and MariaDB.
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")

Comments

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.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.