Avatar billede Mik2000 Professor
30. juni 2022 - 18:55 Der er 8 kommentarer og
1 løsning

MariaDB og JSON data

Hej

Jeg har et JSON felt i min MariaDB database kaldet field for nemhedens skyld her
field indeholder {}

Hvis jeg kører nedenstående
UPDATE table SET field = JSON_UNQUOTE(JSON_SET(field, '$.jsonObject', JSON_COMPACT('{"87654321":"100.00"}'))) WHERE id = 4

Så indeholder den
{"jsonObject": {"87654321": "100.00"}}

Hvis jeg så vil have den til at indeholde noget mere f.eks.
{"jsonObject": {"87654321": "100.00"}, {"12345678": "500.00"}}

Så tænkte jeg at jeg kunne køre
UPDATE table SET field = JSON_UNQUOTE(JSON_SET(field, '$.jsonObject', JSON_COMPACT('{"12345678":"500.00"}'))) WHERE id = 4

ELLER

UPDATE table SET field = JSON_INSERT(field , '$.jsonObject', JSON_COMPACT({"12345678":"500.00"})) WHERE id = 4

Men begge de 2 matcher nu 0 rækker

Så hvordan får jeg et ekstra object ind og ligge under
jsonObject

------------------------------------------------------------------------------------------------------

Ideen er at jeg i feltet gerne vil have flere objecter som kan indeholde flere objecter - f.eks.
{
"jsonObject": {"87654321": "100.00"}, {"12345678": "500.00"},
"andetObject": {"55555": "11111"}, {"5555": "23232"},
tredjeObject": {"a": "1"}, {"b": "2"}, {"c": "2"},
}
Derfor kan jeg ikke bare lave nyt object i stedet for jsonObject - jeg skal have dem ind og ligge i det

-------------------

Håber du kan hjælp :)
Avatar billede arne_v Ekspert
30. juni 2022 - 19:19 #1
Jeg kan godt prøve at eksperimentere og se hvilke JSON fuktioner der skal bruges for at tilføje de felter.

Men hvis det nu skal laves af en applikation Java/PHP/C#/Python/whatever hvorfor så ikke lave en SELECT der henter al JSON, manipulere JSON i applikationen og så gemme den opdaterede JSON med en simpel UPDATE SET?
Avatar billede Mik2000 Professor
30. juni 2022 - 21:03 #2
Det gør jeg også normalt. Men lige netop dette felt er sådan et optionsfelt hvor der kan komme mange forskellige ting i, og der kan ende med at være en halvstor mængde data - samtidige kan det blive manipuleret flere steder fra.

Så jeg tænkte at hvis man kunne manipulere det direkte i det objekt som det drejede sig om, så vil man nedsætte risiko for fejl og samtidige måske optimere lidt med de indbyggede funktioner

Samtidige tænkte jeg også det gav god mening med de JSON funktioner der er kommet netop til det samme

Men jeg tror der er noget jeg misser med de funktioner, fordi f.eks. JSON_INSERT skulle være lave til at indsætte noget - men når jeg har indsat den første så kan den ikke indsætte mere - så må være noget jeg har gjort forkert - men har ingen ide om hvor fejlen ligger

Men det vil da være nice hvis det kunne lade sig gøre - så vil det også være super nemt at slette et enkelt element
Avatar billede Mik2000 Professor
30. juni 2022 - 21:13 #3
Det er mega pænt af dig du gider - du har snart hjulpet mig en del gange herinde :)
Avatar billede arne_v Ekspert
30. juni 2022 - 21:13 #4
Medmindre vi taler om JSON i MB størrelse, så tror jeg ikke at hent alt og gem alt er dyrt.

Men jeg kan godt prøve at lege lidt med de JSON funktioner.
Avatar billede arne_v Ekspert
01. juli 2022 - 02:16 #5
Jeg tror at der er et eller andet jeg har misforstået. JSON_INSERT virker for mig.

mysql> CREATE TABLE mik (
    ->    id INTEGER NOT NULL,
    ->    doc JSON,
    ->    PRIMARY KEY(id)
    -> );
Query OK, 0 rows affected (0.04 sec)

mysql> INSERT INTO mik VALUES(1, '{}');
Query OK, 1 row affected (0.03 sec)

mysql> SELECT doc FROM mik WHERE id = 1;
+------+
| doc  |
+------+
| {}  |
+------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.a', 123);
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+------------+
| doc        |
+------------+
| {"a": 123} |
+------------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.b', 'ABC');
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+------------------------+
| doc                    |
+------------------------+
| {"a": 123, "b": "ABC"} |
+------------------------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.c', JSON_ARRAY(123, 456));
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+-----------------------------------------+
| doc                                    |
+-----------------------------------------+
| {"a": 123, "b": "ABC", "c": [123, 456]} |
+-----------------------------------------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.d', JSON_ARRAY('ABC', 'DEF'));
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+--------------------------------------------------------------+
| doc                                                          |
+--------------------------------------------------------------+
| {"a": 123, "b": "ABC", "c": [123, 456], "d": ["ABC", "DEF"]} |
+--------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.e', JSON_OBJECT('foo', 123, 'bar',
'ABC'));
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+-----------------------------------------------------------------------------------------------+
| doc                                                                                          |
+-----------------------------------------------------------------------------------------------+
| {"a": 123, "b": "ABC", "c": [123, 456], "d": ["ABC", "DEF"], "e": {"bar": "ABC", "foo": 123}} |
+-----------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> DROP TABLE mik;
Query OK, 0 rows affected (0.02 sec)
Avatar billede erikjacobsen Ekspert
01. juli 2022 - 11:44 #6
Du siger du gerne vil have

{
"jsonObject": {"87654321": "100.00"}, {"12345678": "500.00"},
...
}

Det kan man ikke. "jsonObject" kan pege på een ting, enten streng, tal, dict, eller liste. Det er måske det sidste du vil? Altså:

{
"jsonObject": [ {"87654321": "100.00"}, {"12345678": "500.00"}  ],
...
}
Avatar billede arne_v Ekspert
01. juli 2022 - 16:10 #7
Mere avanceret eksempel:

mysql> CREATE TABLE mik (
    ->    id INTEGER NOT NULL,
    ->    doc JSON,
    ->    PRIMARY KEY(id)
    -> );
Query OK, 0 rows affected (0.03 sec)

mysql> INSERT INTO mik VALUES(1, '{}');
Query OK, 1 row affected (0.00 sec)

mysql> SELECT doc FROM mik WHERE id = 1;
+------+
| doc  |
+------+
| {}  |
+------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.a', 123) WHERE id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+------------+
| doc        |
+------------+
| {"a": 123} |
+------------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.b', 'ABC') WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+------------------------+
| doc                    |
+------------------------+
| {"a": 123, "b": "ABC"} |
+------------------------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.c', '{}') WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+-----------------------------------+
| doc                              |
+-----------------------------------+
| {"a": 123, "b": "ABC", "c": "{}"} |
+-----------------------------------+
1 row in set (0.00 sec)

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.c',JSON_SET(doc->>'$.c', '$.c1', JSON_OBJECT())) WHERE id = 1;
Query OK, 1 row affected (0.03 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.c', JSON_SET(doc->>'$.c', '$.c1', JSON_SET(doc->>'$.c.c1', '$.c1x', JSON_OBJECT('x', 1)))) WHERE id = 1;
Query OK, 1 row affected (0.02 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.c', JSON_SET(doc->>'$.c', '$.c1', JSON_SET(doc->>'$.c.c1', '$.c1y', JSON_OBJECT('y', 2)))) WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.c',JSON_SET(doc->>'$.c', '$.c2', JSON_OBJECT())) WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.c', JSON_SET(doc->>'$.c', '$.c2', JSON_SET(doc->>'$.c.c2', '$.c2x', JSON_OBJECT('x', 3)))) WHERE id = 1;
Query OK, 1 row affected (0.00 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> UPDATE mik SET doc = JSON_SET(doc, '$.c', JSON_SET(doc->>'$.c', '$.c2', JSON_SET(doc->>'$.c.c2', '$.c2y', JSON_OBJECT('y', 4)))) WHERE id = 1;
Query OK, 1 row affected (0.01 sec)
Rows matched: 1  Changed: 1  Warnings: 0

mysql> SELECT doc FROM mik WHERE id = 1;
+-------------------------------------------------------------------------------------------------------------------+
| doc                                                                                                              |
+-------------------------------------------------------------------------------------------------------------------+
| {"a": 123, "b": "ABC", "c": {"c1": {"c1x": {"x": 1}, "c1y": {"y": 2}}, "c2": {"c2x": {"x": 3}, "c2y": {"y": 4}}}} |
+-------------------------------------------------------------------------------------------------------------------+
1 row in set (0.00 sec)

mysql> SELECT doc->>'$.c.c1.c1x',doc->>'$.c.c2.c2y' FROM mik;
+--------------------+--------------------+
| doc->>'$.c.c1.c1x' | doc->>'$.c.c2.c2y' |
+--------------------+--------------------+
| {"x": 1}          | {"y": 4}          |
+--------------------+--------------------+
1 row in set (0.00 sec)

mysql> DROP TABLE mik;
Query OK, 0 rows affected (0.01 sec)
Avatar billede Mik2000 Professor
02. juli 2022 - 13:43 #8
Mange tak for hjælpen - tror jeg har det jeg skal bruge nu :)
Avatar billede arne_v Ekspert
03. juli 2022 - 01:36 #9
PHP:

<?php
$fromdb = '{"a": 123, "b": "ABC"}';
echo $fromdb . "\r\n";
$o = json_decode($fromdb, true);
$o['c'] = array('c1' => array('c1x' => array('x' => 1), 'c1y' => array('y' => 2)), 'c2' => array('c2x' => array('x' => 3), 'c2y' => array('y' => 4)));
$todb = json_encode($o);
echo $todb . "\r\n";
?>


{"a": 123, "b": "ABC"}
{"a":123,"b":"ABC","c":{"c1":{"c1x":{"x":1},"c1y":{"y":2}},"c2":{"c2x":{"x":3},"c2y":{"y":4}}}}
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester