I am using some native JSON fields to store information about some application entities in a MySQL 5.7.10 database. I can have 'N' rows per "entity" and need to roll-up and merge the JSON objects together, and any conflicting keys should replace instead of merge. I can do this through code, but if I can do it natively and efficiently in MySQL even better.
I have attempted this using a combination of GROUP_CONCAT
and JSON_MERGE, but I've run into two issues:
GROUP_CONCAT
as a valid argumentIs this possible with the current MySQL JSON implementation?
JSON_AGG combines values and returns the combined data as a single JSON row. NULL values are included in the aggregation.
In MySQL, JSON values are written as strings. MySQL parses any string used in a context that requires a JSON value, and produces an error if it is not valid as JSON.
JSON_ARRAYAGG returns a JSON array containing an element for each value in a given set of JSON or SQL values. It acts on a column or an expression that evaluates to a single value. Returns NULL in the case of an error, or if the result contains no rows. JSON_ARRAYAGG cannot currently be used as a window function.
JSON_OBJECTAGG( key , value ) Takes two column names or expressions as arguments, the first of these being used as a key and the second as a value, and returns a JSON object containing key-value pairs. Returns NULL if the result contains no rows, or in the event of an error.
You could do something like the following:
SELECT
CAST(CONCAT(
'[',
GROUP_CONCAT(
DISTINCT JSON_OBJECT(
'foo', mytable.foo,
'bar', mytable.bar
)
),
']'
) AS JSON) AS myJsonArr
FROM mytable
GROUP BY mytable.someGroup;
- JSON_MERGE won't take the results of GROUP_CONCAT as a valid argument
GROUP_CONCAT
gives a,b,c,d
, not a JSON array. Use JSON_ARRAYAGG
(introduced in MySQL 5.7.22), which works just like group_concat, but gives a correct array ["a", "b", "c", "d"]
, that should be accepted with JSON functions.
Prior to 5.7.22, you need to use a workaround:
cast(
concat('["', // begin bracket and quote
group_concat(`field` separator '", "'), // separator comma and quotes
'"]' // end quote and bracket
) as json
)
- JSON_MERGE combines conflicting keys instead of replacing them. What I really need is more of a JSON_SET but with 'N' number of JSON docs instead of "key, value" notation.
Use JSON_MERGE_PATCH
instead, as introduced in MySQL 5.7.22. JSON_MERGE
is a synonym for JSON_MERGE_PRESERVE
.
See https://dev.mysql.com/doc/refman/5.7/en/json-function-reference.html.
Read my Best Practices for using MySQL as JSON storage.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With