2013-03-29 39 views
7

Ho le seguenti tabelle e il loro rapporto. Sto memorizzando i dati JSON nella tabella client_services. È il loro modo di recuperare i valori JSON usando la query mysql. come:Come recuperare i dati JSON da mysql?

select getJson("quota") as quota, client_id from client_services where service_id =1;  

O

Posso normalizzare tavolo client_services ulteriormente?

Servizi:

+----+-----------------------+--------------------------------------------------------+ 
| id | name     | description           | 
+----+-----------------------+--------------------------------------------------------+ 
| 1 | MailBox    |              | 
| 2 | SMS     |              | 
| 3 | FTP     |              | 
+----+-----------------------+--------------------------------------------------------+ 

service_features:

+----+------------+----------------------------------+------------------------+ 
| id | service_id | name        | description   | 
+----+------------+----------------------------------+------------------------+ 
| 10 |   1 | Forwarding      | Forward Mail   | 
| 11 |   1 | Archive       | Archive Mail   | 
| 12 |   1 | WebMail       | NULL     | 
| 13 |   1 | IMAP        | NULL     | 
| 14 |   2 | Web SMS       | NULL     | 
+----+------------+----------------------------------+------------------------+ 

client_services:

+-----+-----------+------------+-------------------------------------------------------------------------------------------+ 
| id | client_id | service_id | service_values                   | 
+-----+-----------+------------+-------------------------------------------------------------------------------------------+ 
| 100 |  1000 |   1 |{ "quota": 100000,"free_quota":20000,"total_accounts":200,"data_transfer":1000000}   | 
| 101 |  1000 |   2 |{ "quota": 200 }                   | 
| 102 |  1000 |   3 |{ "data_transfer":1000000}                 | 
| 103 |  1001 |   1 |{ "quota": 1000000,"free_quota":2000,"total_accounts":200,"data_transfer":1000000}   | 
| 104 |  1001 |   2 |{ "quota": 500 }                   | 
| 105 |  1002 |   2 |{ "quota": 600 }                   | 
+-----+-----------+------------+-------------------------------------------------------------------------------------------+ 

client_feature_mappers:

+-----+-------------------+--------------------+-----------+ 
| id | client_service_id | service_feature_id | client_id | 
+-----+-------------------+--------------------+-----------+ 
|10000|    100|     10 |  1000| 
|10001|    100|     11 |  1000| 
|10002|    100|     12 |  1000| 
|10003|    100|     13 |  1000| 
|10004|    101|     14 |  1000| 
|10005|    103|     10 |  1001| 
|10006|    101|     11 |  1001| 
|10007|    101|     12 |  1001| 
|10008|    101|     13 |  1001| 
|10009|    105|     14 |  1002| 
+-----+-------------------+--------------------+-----------+ 
+1

Perché si desidera archiviare JSON non elaborato in una tabella? Non avrebbe più senso memorizzare i dati in un formato più logico e costruire il JSON a un livello più alto nello stack? – david99world

risposta

15

Dal momento che molte persone mi hanno fatto questa domanda personalmente, ho pensato di dare a questa risposta una seconda revisione. Ecco a gist that has the complete SQL with SELECT, Migration and View Creation e a live sql fiddle(disponibilità non garantita per il violino).

Diciamo che avete tabella (denominata: JSON_TABLE) come questo:

ID CITY  POPULATION_JSON_DATA 
----------------------------------------------------------------------- 
1 LONDON  {"male" : 2000, "female" : 3000, "other" : 600} 
2 NEW YORK {"male" : 4000, "female" : 5000, "other" : 500} 

per selezionare ogni campi JSON, si può fare:

SELECT 
    ID, CITY, 
    json_extract(POPULATION_JSON_DATA, '$.male') AS POPL_MALE, 
    json_extract(POPULATION_JSON_DATA, '$.female') AS POPL_FEMALE, 
    json_extract(POPULATION_JSON_DATA, '$.other') AS POPL_OTHER 
FROM JSON_TABLE; 

che si traduce:

ID CITY  POPL_MALE POPL_FEMALE POPL_OTHER 
----------------------------------------------------------------- 
1 LONDON 2000  3000   600 
2 NEW YORK 4000  5000   500 

Potrebbe essere un'operazione costosa da eseguire in base alla dimensione dei dati e alla complessità di JSON. Io suggerisco di usare per

  1. migrazione di tabella per dividere database (Vedere l'Appendice 2-B in GIST)
  2. Almeno creare una vista (vedi Appendice 2-C in pazienti con GIST)

Attenzione per: Si può avere jSON iniziando con le doppie virgolette (stringata):

"{"male" : 2000, "female" : 3000, "other" : 600}" 

Testato con Mysql 5.7 su Ubuntu e Mac OSX Sierra.

+0

(più 1) per "uso solo per la migrazione dei dati" – user3581203

1

Il database è per la memorizzazione e il recupero dei dati, non per formattarli. MySQL restituisce le cose in forma tabellare ed è così che funziona. Quindi se vuoi avere JSON devi convertire questi dati tabulari in JSON tu stesso, nel tuo codice.

+0

Ho bisogno della query mysql che recupera i dati json, perché alcuni server come dovecot (Imap, pop server) interrogano direttamente su mysql, altrimenti l'ho fatto attraverso il codice. Mi sono imbattuto in qualche MysDF UDF come http://blog.kazuhooku.com/2011/09/mysqljson-mysql-udf-for-parsing-json.html. vale la pena installarlo. –

+0

@pankajghadge questa è una specie di strana architettura, ovviamente stai risolvendo i tuoi problemi con strumenti sbagliati. Ma puoi scrivere la procedura mysql che formatterà i dati tabulari in JSON, non è così difficile. – Andrey

+0

non ho esperienza nello scrivere la funzione mysql. Sono in grado di normalizzare ulteriormente la tabella, ma aumenterà il tempo di output della query. –

2

In primo luogo si dovrebbe essere consapevoli del fatto che il modello in alto non è in Prima forma normale, il che significa che si dovrebbe avere un solo valore in ogni campo. Tuttavia, questa definizione dipende dalle esigenze di elaborazione della query dell'applicazione.

Quindi, se tutto ciò che si desidera è mettere un gruppo di dati JSON in un campo e restituirlo all'applicazione così com'è, allora va bene. È possibile restituire tutti i dati JSON e consentire all'applicazione di selezionare gli attributi JSON desiderati.

Ma se avete domande, come nel vostro caso, avendo criteri o espressioni di campo che esaminano i dettagli dei dati JSON, allora è decisamente un no-go. Sarà un incubo nella complessità delle query e nell'elaborazione lenta.

È inoltre possibile normalizzare ulteriormente le tabelle per sostituire completamente la struttura dati JSON. Tuttavia, se la tua applicazione necessita di uno schema flessibile, forse la ragione principale per utilizzare i DB NOSQL, ma sei bloccato con MySQL, ci sono due soluzioni:

a) usa MySQL 5.6 (o MariaDB v. ??) per NoSQL supporto (non ho guardato in dettagli) http://www.computerworld.com/s/article/9236511/MySQL_5.6_tackles_NoSQL_competitors colonne dinamiche di MariaDB: https://kb.askmonty.org/en/dynamic-columns/

b) utilizzare MySQL, senza uno schema esplicito, vedi qui per una soluzione molto ben fatto, che non ha problemi di scalabilità: http://backchannel.org/blog/friendfeed-schemaless-mysql

3

È possibile utilizzare la funzione MySQL SUBSTRING_INDEX per suddividere la stringa JSON:

SELECT 
SUBSTRING_INDEX(
SUBSTRING_INDEX(
    SUBSTRING_INDEX(service_values, 'quota', -1), 
    '": ', -1), 
' ', 1) AS quota, 
client_id 
FROM client_services 
WHERE service_id=1; 
Problemi correlati