Sprawdź, czy tablica JSON w MySQL zawiera obiekt, którego klucz zawiera określoną datę

18

próbuję dowiedzieć się, czy w tablicy JSON znajduje się wiersz zawierający konkretną datę

Powiedzmy, że moje dane wyglądają tak:

Aplikacje stołowe:

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

Jak mogę znaleźć wszystkie aplikacje, których dane zawierają datę '2016-04-26'?

Zasadniczo mogę to zrobić:

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

Które zwraca:

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

Ale jeśli spróbuję użyć json_extractw WHEREklauzuli, mogę go użyć tylko wtedy, gdy wyraźnie podam klucz tablicy w json_extractargumencie path, tak jak poniżej:

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

co poprawnie zwraca wiersz o id 4.

Ale jeśli spróbuję użyć symbolu wieloznacznego na ścieżce, nie będzie to już działać:

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

to powinno zwrócić wiersze 2, 3, 4.

Próbowałem wielu innych opcji / odmian, ale nie mogę znaleźć sposobu, aby poprawnie ustrukturyzować zapytanie.

Czy coś takiego jest w ogóle możliwe przy obecnej implementacji MySQL JSON?

Klemen
źródło

Odpowiedzi:

15

Jednym z rozwiązań dostarczonych przez Morgan Tucker - @morgo jest json_containstakie użycie :

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

Na razie odpowiedź jest OK, ale wierzę, że może mieć pewne problemy z wydajnością i wydaje mi się trochę hacking (patrz następne zapytanie) - ale poradzę sobie z nimi, kiedy tam dotrę :)

Gdybym musiał zapytać o zakres dat (od 2016-04-24do 2016-04-26), musiałbym dodać osobnika json_containsdla każdego dnia w określonym przedziale czasowym w następujący sposób:

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

Zwróciłoby to nieprawidłowe dane, gdybym miał dateklucz zagnieżdżony gdzie indziej

Więc jeśli masz inne rozwiązanie, chciałbym wiedzieć

Klemen
źródło
jako wariant - zdefiniuj maksymalną głębokość tablicy dat - WYBIERZ MAKS (json_depth (dane - >> '$ [*]. data')), niż przez pętlę w procedurze przechowywanej wypakuj do tabel temp - id i wybraną datę - wybierz id, json_extract ( data, „$ [0] .date”) jako „data” z aplikacji, następnie wybierz id, json_extract ( data, „$ [1] .date”) jako „data” z aplikacji itp. niż zastosuj wszystkie filtry i mam listę id
a_vlad
dałeś mi wskazówkę, jak korzystać ze składni json_contains
Jimmy Ilenloa