Understanding the -> Operator in MySQL

In MySQL, we can use the -> operator to extract data from a JSON document.

We provide the column that contains the JSON document to the left of the operator, and the path to the value that we want to extract to the right.

The -> operator is an alias for the two-argument form of the JSON_EXTRACT() function.

Syntax

The syntax goes like this:

column->path

Where column is the column that contains the JSON document, and path is the path to the value we want to extract.

Example

Suppose we have the following table called Pets:

SELECT * 
FROM Pets;

Result:

+-------+-----------------------------------------------+
| PetId | PetName                                       |
+-------+-----------------------------------------------+
|     1 | {"name": "Wag", "type": "Dog", "weight": 20}  |
|     2 | {"name": "Bark", "type": "Dog", "weight": 10} |
|     3 | {"name": "Meow", "type": "Cat", "weight": 7}  |
+-------+-----------------------------------------------+

We can see that the PetName column contains JSON.

We can use the -> operator to extract data from one of the fields within those JSON documents:

SELECT PetName -> '$.name'
FROM Pets;

Result:

+---------------------+
| PetName -> '$.name' |
+---------------------+
| "Wag"               |
| "Bark"              |
| "Meow"              |
+---------------------+

Here’s another example that also extracts the weight for each pet:

SELECT 
    PetId,
    PetName -> '$.name',
    PetName -> '$.weight'
FROM Pets;

Result:

+-------+---------------------+-----------------------+
| PetId | PetName -> '$.name' | PetName -> '$.weight' |
+-------+---------------------+-----------------------+
|     1 | "Wag"               | 20                    |
|     2 | "Bark"              | 10                    |
|     3 | "Meow"              | 7                     |
+-------+---------------------+-----------------------+

In the WHERE Clause

We’re not limited to just the SELECT list. We can use the -> operator in place of any column reference.

Here’s an example of using -> in a WHERE clause:

SELECT *
FROM Pets
WHERE PetName -> '$.name' = 'Wag';

Result:

+-------+----------------------------------------------+
| PetId | PetName                                      |
+-------+----------------------------------------------+
|     1 | {"name": "Wag", "type": "Dog", "weight": 20} |
+-------+----------------------------------------------+

In the ORDER BY Clause

Here’s an example of using the -> operator in an ORDER BY clause:

SELECT *
FROM Pets
ORDER BY PetName -> '$.name';

Result:

+-------+-----------------------------------------------+
| PetId | PetName                                       |
+-------+-----------------------------------------------+
|     2 | {"name": "Bark", "type": "Dog", "weight": 10} |
|     3 | {"name": "Meow", "type": "Cat", "weight": 7}  |
|     1 | {"name": "Wag", "type": "Dog", "weight": 20}  |
+-------+-----------------------------------------------+

We can see that the pets are now ordered based on their names.

Let’s order by weight:

SELECT *
FROM Pets
ORDER BY PetName -> '$.weight';

Result:

+-------+-----------------------------------------------+
| PetId | PetName                                       |
+-------+-----------------------------------------------+
|     3 | {"name": "Meow", "type": "Cat", "weight": 7}  |
|     2 | {"name": "Bark", "type": "Dog", "weight": 10} |
|     1 | {"name": "Wag", "type": "Dog", "weight": 20}  |
+-------+-----------------------------------------------+

Remove Quotes

We have a couple of options for removing the quotes from strings that we return from the JSON document.

We can use the JSON_UNQUOTE() function:

SELECT 
    PetName -> '$.name' AS "Quoted",
    JSON_UNQUOTE(PetName -> '$.name') AS "Unquoted"
FROM Pets;

Result:

+--------+----------+
| Quoted | Unquoted |
+--------+----------+
| "Wag"  | Wag      |
| "Bark" | Bark     |
| "Meow" | Meow     |
+--------+----------+

Or we can use the ->> operator:

SELECT 
    PetName -> '$.name' AS "Quoted",
    PetName ->> '$.name' AS "Unquoted"
FROM Pets;

Result:

+--------+----------+
| Quoted | Unquoted |
+--------+----------+
| "Wag"  | Wag      |
| "Bark" | Bark     |
| "Meow" | Meow     |
+--------+----------+

The ->> operator provides us with a more concise way of returning the same data with less code.

How EXPLAIN & DESCRIBE Present the -> Operator

When we use the EXPLAIN or DESCRIBE statements to return information about our query’s execution, they present the query as if we’d used JSON_EXTRACT() instead of the -> operator.

EXPLAIN SELECT PetName -> '$.name' FROM Pets;

Result:

+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
| id | select_type | table | partitions | type | possible_keys | key  | key_len | ref  | rows | filtered | Extra |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
|  1 | SIMPLE      | Pets  | NULL       | ALL  | NULL          | NULL | NULL    | NULL |    3 |   100.00 | NULL  |
+----+-------------+-------+------------+------+---------------+------+---------+------+------+----------+-------+
1 row in set, 1 warning (0.00 sec)

Now let’s look at the warning:

SHOW WARNINGS;

Result:

+-------+------+------------------------------------------------------------------------------------------------------------------+
| Level | Code | Message                                                                                                          |
+-------+------+------------------------------------------------------------------------------------------------------------------+
| Note  | 1003 | /* select#1 */ select json_extract(`test`.`pets`.`PetName`,'$.name') AS `PetName -> '$.name'` from `test`.`pets` |
+-------+------+------------------------------------------------------------------------------------------------------------------+

The same applies to the ->> operator.