Lihat apakah array JSON di MySQL berisi objek yang kuncinya menyimpan tanggal tertentu

17

Saya mencoba mencari tahu apakah ada baris yang berisi tanggal tertentu di dalam array JSON

Katakanlah data saya terlihat seperti ini:

Aplikasi meja:

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

Bagaimana saya bisa menemukan semua aplikasi yang datanya berisi tanggal '2016-04-26'?

Jadi pada dasarnya saya bisa melakukan ini:

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

Yang mengembalikan:

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

Tetapi jika mencoba menggunakan json_extractdalam WHEREklausa saya hanya bisa menggunakannya jika saya secara eksplisit memberi tahu kunci array dalam json_extractargumen path, seperti:

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

yang mengembalikan baris dengan benar dengan id 4.

Tetapi jika saya mencoba menggunakan wildcard di jalan maka itu tidak lagi berfungsi:

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

ini harus mengembalikan baris 2, 3, 4.

Saya mencoba banyak opsi / variasi lain tetapi sepertinya saya tidak dapat menemukan cara untuk menyusun kueri dengan benar.

Apakah hal seperti ini bahkan mungkin dengan implementasi MySQL JSON saat ini?

Klemen
sumber

Jawaban:

14

Salah satu solusi yang disediakan oleh Morgan Tucker - @morgo adalah menggunakan json_containsseperti:

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

Untuk saat ini jawabannya OK, tetapi saya percaya itu dapat memiliki beberapa masalah kinerja dan terasa agak meretas bagi saya (lihat pertanyaan berikutnya) - tetapi saya akan mengatasinya ketika saya sampai di sana :)

Jika saya perlu melakukan kueri pada rentang tanggal (dari 2016-04-24hingga 2016-04-26) saya perlu menambahkan invididual json_containsuntuk setiap hari dalam rentang waktu seperti ini:

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

Dan ini akan mengembalikan data yang tidak valid jika saya memiliki datekunci yang bersarang di tempat lain

Jadi, jika Anda memiliki solusi yang berbeda, saya ingin tahu

Klemen
sumber
sebagai varian - tentukan kedalaman maksimum array tanggal - SELECT MAX (json_depth (data - >> '$ [*]. date')), daripada melalui loop dalam ekstrak prosedur tersimpan ke temp tables - id dan tanggal yang dipilih - pilih id, json_extract ( data, "$ [0] .date") sebagai 'date' dari aplikasi, daripada- pilih id, json_extract ( data, "$ [1] .date") sebagai 'date' dari aplikasi, dan lain-lain daripada menerapkan semua filter dan memiliki daftar id
a_vlad
Anda memberi saya petunjuk tentang cara menggunakan sintaks json_contains
Jimmy Ilenloa