mariadb - JSON Column update element inside a nested list - mysql

I have the following data in a json column:
[
["model-1", 0.06232],
["model-2", 0.33587],
["model-3", 0.04962],
["model-4", 0.235],
["model-5", 0.31719]
]
My goal is to prepend a string to the first element of each inner list so that the output becomes:
[
["somestr/model-1", 0.06232],
["somestr/model-2", 0.33587],
["somestr/model-3", 0.04962],
["somestr/model-4", 0.235],
["somestr/model-5", 0.31719]
]
I have been able to "extract" the first elements using mariadb JSON_EXTRACT as follows:
SELECT JSON_EXTRACT(factors, '$[*][0]') FROM my_table;
But could not get any further.
Is it possible to achieve this using mariadb / mysql JSON functions? Or am I better off doing this on the application level?

Related

MariaDB - compare two json objects

In MySQL 5.7 I can compare two json objects where the order of the key are ignored e.g the following two json string are equal:
SELECT CAST('{"num": "27,28", "date": "2019-11-01"}' AS JSON) = CAST('{"date": "2019-11-01", "num": "27,28"}' AS JSON);
In mariadb there is no such json data type and so the above will return false.
Is there any way to accomplish the same in mariadb?
Note I've seen the following post and the solution is not ideal: Compare JSON values in MariaDB

How to use JSON_ARRAY_APPEND when path does not exist in JSON doc?

Imaging the existing JSON doc:
{
"first": "data",
"second": [1,2,3]
}
When I try to execute:
JSON_ARRAY_APPEND(doc,'$.third',4)
I expect mysql to create the parameter as an empty array and add my element into that array resulting in:
{
"first": "data",
"second": [1,2,3],
"third": [4]
}
This however is not the case. I am trying to do this in an UPDATE query to add data into the db using something similar to:
UPDATE mytable
SET myjson=JSON_ARRAY_APPEND(myjson,'$.third',4)
WHERE ...
I am using mysql 8.0.16 if that makes any difference. I am not getting any errors, just 0 row(s) affected
Your JSON is not an array, so rather than JSON_ARRAY_APPEND(), you can consider using JSON_MERGE_PATCH() function if the order of the keys do not matter :
UPDATE mytable
SET myjson = JSON_MERGE_PATCH(myjson, '{"third": [4]}')
Demo
According to Normalization principle ; To make lookups more efficient, MySQL also sorts the keys of a JSON object. You should be aware that the result of this ordering is subject to change and not guaranteed to be consistent across releases.

Fetching object JSON array using JSON_QUERY in MariaDB

How do I access the value of a object property, inside an array, using JSON_QUERY in MariaDB? I have a JSON field with following data, and want to access the value of the section property.
[
[
{"section": "search"}
]
]
The following SQL is returning NULL
SELECT JSON_QUERY('[[{"section": "search"}]]', '$[0][0].section') FROM mytable
For anyone else having the same issue, you have to use JSON_VALUE for accessing scalar values. The following query gives the expected result.
SELECT JSON_VALUE'[[{"section": "search"}]]', '$[0][0].section') FROM mytable;
JSON_QUERY vs JSON_VALUE

Returning MySQL data as an OBJECT rather than an ARRAY (Knex)

Is there a way to get the output of a MySQL query to list rows in the following structure
{
1:{voo:bar,doo:dar},
2:{voo:mar,doo:har}
}
as opposed to
[
{id:1,voo:bar,doo:dar},
{id:2,voo:mar,doo:har}
]
which I then have to loop through to create the desired object?
I should add that within each row I am also concatenating results to form an object, and from what I've experimented with you can't group_concatenate inside a group_concatenation. As follows:
knex('table').select(
'table.id',
'table.name',
knex.raw(
`CONCAT("{", GROUP_CONCAT(DISTINCT
'"',table.voo,'"',':','"',table.doo,'"'),
"}") AS object`
)
.groupBy('table.id')
Could GROUP BY be leveraged in any way to achieve this? Generally I'm inexperienced at SQL and don't know what's possible and what's not.

Regular expression to remove the key:value from hash / json

Suppose I have following json and I want to skip the entry "data_type" from it.
{
"marketing_type":"FIT",
"controllable":"true",
"plannable":"true",
"sbm_qualified":"true",
"marginal_cost":"{:type=>\"float\", :label=>\"Marginal Cost to steer\",:unit=>\"$/MWh\", :default=>100} must be float.",
"data_type": "any_value",
"start_cost":"{:type=>\"float\", :label=>\"Start Cost\", :unit=>\"$\",:default=>0} must be float."
}
Expected output is "data_type" entry should be removed from above.
Instead of using regex and string manipulations, and if you're running at least MySQL 5.7, you can use one of the built-in JSON functions, json_remove:
update table_name set column_name = json_remove(column_name, "$.data_type")