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