Überprüfen Sie, ob ein JSON-Array in MySQL ein Objekt enthält, dessen Schlüssel ein bestimmtes Datum enthält

17

Ich versuche herauszufinden, ob es eine Zeile gibt, die ein bestimmtes Datum in einem JSON-Array enthält

Angenommen, meine Daten sehen folgendermaßen aus:

Tischanwendungen:

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"}]

Wie finde ich alle Anwendungen, deren Daten das Datum enthalten '2016-04-26'?

Im Grunde kann ich das tun:

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

Welches gibt zurück:

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"]

Wenn ich jedoch versuche, es json_extractin der WHEREKlausel zu verwenden, kann ich es nur verwenden, wenn ich den Schlüssel des Arrays im Pfadargument explizit json_extractwie folgt sage :

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

was die Zeile mit der ID 4 korrekt zurückgibt.

Wenn ich jedoch versuche, einen Platzhalter im Pfad zu verwenden, funktioniert dies nicht mehr:

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

Dies sollte die Zeilen 2, 3, 4 zurückgeben.

Ich habe viele andere Optionen / Variationen ausprobiert, aber ich kann anscheinend keinen Weg finden, die Abfrage richtig zu strukturieren.

Ist so etwas mit der aktuellen Implementierung von MySQL JSON überhaupt möglich?

Klemen
quelle

Antworten:

14

Eine von Morgan Tucker - @morgo bereitgestellte Lösung lautet json_containswie folgt :

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

Im Moment ist die Antwort in Ordnung, aber ich glaube, dass es einige Leistungsprobleme geben kann und sich für mich etwas hackisch anfühlt (siehe nächste Frage) - aber ich werde mich um diese kümmern, wenn ich dort ankomme :)

Wenn ich nach einem Datumsbereich (von 2016-04-24bis 2016-04-26) fragen müsste, müsste ich json_containsfür jeden Tag in der folgenden Zeitspanne einen individuellen hinzufügen :

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"}')

Und dies würde ungültige Daten zurückgeben, wenn ich dateirgendwo anders einen Schlüssel verschachtelt hätte

Wenn Sie also eine andere Lösung haben, würde ich gerne wissen

Klemen
quelle
als Variante - maximale Tiefe des Datums-Arrays definieren - SELECT MAX (json_depth (data - >> '$ [*]. date'), dann durch die Schleife in der gespeicherten Prozedur extrahieren, um Tabellen zu temp - ID und ausgewähltes Datum - ID auswählen, json_extract ( data, "$ [0] .date") als "Datum" aus Anwendungen, wählen Sie id, json_extract ( data, "$ [1] .date") als "Datum" aus Anwendungen usw. aus, und wenden Sie dann alle Filter an und haben die Liste von id
a_vlad
Sie gaben mir einen Hinweis auf die Verwendung der Syntax von json_contains
Jimmy Ilenloa