Vea si una matriz JSON en MySQL contiene un objeto cuya clave contiene una fecha específica


17

Estoy tratando de averiguar si hay una fila que contiene una fecha específica dentro de una matriz JSON

Digamos que mis datos se ven así:

Aplicaciones de mesa:

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

¿Cómo puedo encontrar todas las aplicaciones cuyos datos contienen la fecha '2016-04-26'?

Entonces básicamente puedo hacer esto:

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

Que devuelve:

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

Pero si trato de usar json_extracten la WHEREcláusula, solo puedo usarlo si explícitamente le digo a la clave de la matriz en el json_extractargumento de la ruta de acceso de la siguiente manera:

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

que devuelve correctamente la fila con id 4.

Pero si trato de usar un comodín en la ruta, ya no funciona:

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

Esto debería devolver las filas 2, 3, 4.

Intenté muchas otras opciones / variaciones, pero parece que no puedo encontrar una manera de estructurar la consulta correctamente.

¿Es posible algo como esto con la implementación actual de MySQL JSON?

Respuestas:


14

Una solución proporcionada por Morgan Tucker: @morgo es usar json_containsasí:

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

Por ahora, la respuesta está bien, pero creo que puede tener algunos problemas de rendimiento y me parece un poco difícil (vea la siguiente consulta), pero trataré con eso cuando llegue allí :)

Si tuviera que consultar en un rango de fechas (de 2016-04-24a 2016-04-26), necesitaría agregar un invididual json_containspara cada día en el lapso de tiempo de la siguiente manera:

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

Y esto devolvería datos no válidos si tuviera una dateclave anidada en otro lugar

Entonces, si tiene una solución diferente, me gustaría saber


como variante: defina la profundidad máxima de la matriz de fecha: SELECCIONE MÁXIMO (json_depth (datos - >> '$ [*]. fecha')), que a través del bucle en el procedimiento almacenado, extraiga en las tablas temporales - id y fecha seleccionada - seleccione id, json_extract ( data, "$ [0] .date") como 'fecha' de las aplicaciones, que- seleccione id, json_extract ( data, "$ [1] .date") como 'fecha' de las aplicaciones, y etc. que apliquen todos los filtros y tener una lista de identificación
a_vlad

me diste una pista sobre cómo usar la sintaxis json_contains
Jimmy Ilenloa
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.