Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Select, where JSON Array contains

Tags:

So in Laravel 5 there's the handy thing called JSON Where Clauses using MySQL's new ability to store and fetch JSON stored in a column:

User::where('meta->colors', 'red')->get()

would return all rows, where colors in the column meta would be set to red.

Now let's say colors is not a string, but an array containing multiple colors (colors => ['red', 'blue', 'green']).

What would be an efficient way to retrieve all rows, where colors contains e.g. the value red?

like image 522
Elwin Avatar asked Sep 05 '17 12:09

Elwin


People also ask

How do I query a JSON column in SQL?

To query JSON data, you can use standard T-SQL. If you must create a query or report on JSON data, you can easily convert JSON data to rows and columns by calling the OPENJSON rowset function. For more information, see Convert JSON Data to Rows and Columns with OPENJSON (SQL Server).

How do I query Jsonb data in PostgreSQL?

Querying the JSON documentPostgreSQL has two native operators -> and ->> to query JSON documents. The first operator -> returns a JSON object, while the operator ->> returns text. These operators work on both JSON as well as JSONB columns. There are additional operators available for JSONB columns.

What is Json_build_object?

json_build_object(VARIADIC "any") Builds a JSON object out of a variadic argument list. By convention, the argument list consists of alternating keys and values.

What is -> in PostgreSQL?

PostgreSQL provides two native operators -> and ->> to help you query JSON data. The operator -> returns JSON object field by key. The operator ->> returns JSON object field by text.


2 Answers

JSON_CONTAINS() does exactly what you're looking for:

JSON_CONTAINS(target, candidate[, path])

Indicates by returning 1 or 0 whether a given candidate JSON document is contained within a target JSON document, or—if a path argument was supplied—whether the candidate is found at a specific path within the target. — 12.16.3 Functions That Search JSON Values

Currently, Laravel's query builder does not provide a corresponding API. There's an open internals proposal for it though.

In the meantime, you can execute a raw query:

\DB::table('users')->whereRaw(
    'JSON_CONTAINS(meta->"$.colors", \'["red"]\')'
)->get();

Which would return all users that have "red" in their meta->colors JSON field. Note that the -> operator requires MySQL 5.7.9+.

You can also call the whereRaw() directly on an Eloquent model.

Laravel 5.6

As of the 5.6 release, Laravel's query builder contains a new whereJsonContains method.

like image 134
sepehr Avatar answered Oct 07 '22 19:10

sepehr


I think a way would be using the like operator:

User::where('meta->colors', 'like', '%"red"%')

However, this would only work if the values never contain the character " and the delimiters wouldn't change.

like image 20
Elwin Avatar answered Oct 07 '22 18:10

Elwin