Verifica se un array JSON in MySQL contiene un oggetto la cui chiave contiene una data specifica


17

sto cercando di scoprire se esiste una riga che contiene una data specifica all'interno di un array JSON

Supponiamo che i miei dati siano così:

Applicazioni da tavolo:

id | application_id | data
# Rows
1 | 1 | [{"data" : ["some", "data#1"], "date": "2016-04-21"}, {"data" : ["other", "data#1"], "date" : "2016-04-22"}]
2 | 2 | [{"data" : ["some", "data#2"], "date": "2016-04-21"}, {"data" : ["other", "data#2"], "date" : "2016-04-26"}]
3 | 1 | [{"data" : ["some", "data#3"], "date": "2016-04-22"}, {"data" : ["other", "data#3"], "date" : "2016-04-26"}]
4 | 3 | [{"data" : ["some", "data#4"], "date": "2016-04-26"}]

Come posso trovare tutte le applicazioni i cui dati contengono la data '2016-04-26'?

Quindi in pratica posso farlo:

select id, json_extract(`data`, "$[*].date") from applications

Che ritorna:

1 | ["2016-04-21", "2016-04-22"]
2 | ["2016-04-21", "2016-04-26"]
3 | ["2016-04-22", "2016-04-26"]
4 | ["2016-04-26"]

Ma se provo ad usarlo json_extractnella WHEREclausola posso usarlo solo se dico esplicitamente la chiave dell'array json_extractnell'argomento del percorso, in questo modo:

select * from applications where json_extract(`data`, "$[0].date") = "2016-04-26"

che restituisce correttamente la riga con ID 4.

Ma se provo ad usare un carattere jolly nel percorso, allora non funziona più:

select * from applications where json_extract(`data`, "$[*].date") = "2016-04-26"

questo dovrebbe restituire le righe 2, 3, 4.

Ho provato molte altre opzioni / varianti ma non riesco a trovare un modo per strutturare correttamente la query.

È possibile qualcosa del genere anche con l'attuale implementazione di MySQL JSON?

Risposte:


14

Una soluzione fornita da Morgan Tucker - @morgo è quella di utilizzare in questo json_containsmodo:

select * from applications where json_contains(`data`, '{"date" : "2016-04-26"}')

Per ora la risposta è OK, ma credo che possa avere alcuni problemi di prestazioni e mi sembra un po 'hacker (vedi la prossima domanda) - ma mi occuperò di quelli quando arrivo lì :)

Se avessi bisogno di eseguire una query su un intervallo di date (da 2016-04-24a 2016-04-26), avrei bisogno di aggiungere un invito json_containsper ogni giorno nell'intervallo di tempo in questo modo:

select * from applications where json_contains(`data`, '{"date" : "2016-04-26"}') or json_contains(`data`, '{"date" : "2016-04-25"}') or json_contains(`data`, '{"date" : "2016-04-24"}')

E questo restituirebbe dati non validi se avessi una datechiave nidificata altrove

Quindi, se hai una soluzione diversa, vorrei saperlo


come variante - definisce l'array di profondità massima della data - SELEZIONA MAX (json_depth (dati - >> '$ [*]. data')), che attraverso il ciclo nell'estrazione della procedura memorizzata nelle tabelle temporanee - id e data selezionata - seleziona id, json_extract ( data, "$ [0] .date") come 'data' dalle applicazioni, quindi selezionare id, json_extract ( data, "$ [1] .date") come 'data' dalle applicazioni, ecc. di applicare tutti i filtri e avere un elenco di id
a_vlad

mi hai dato un indizio su come usare la sintassi json_contains
Jimmy Ilenloa,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.