Veja se uma matriz JSON no MySQL contém um objeto cuja chave contém uma data específica


17

Estou tentando descobrir se existe uma linha que contém uma data específica dentro de uma matriz JSON

Digamos que meus dados sejam assim:

Aplicações 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"}]

Como posso encontrar todos os aplicativos cujos dados contêm a data '2016-04-26'?

Então, basicamente, eu posso fazer isso:

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

Que retorna:

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

Mas se tentar usar json_extracta WHEREcláusula, só posso usá-la se eu disser explicitamente a chave da matriz no json_extractargumento do caminho, da seguinte maneira:

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

que retorna corretamente a linha com o ID 4.

Mas se eu tentar usar um curinga no caminho, ele não funcionará mais:

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

isso deve retornar as linhas 2, 3, 4.

Tentei muitas outras opções / variações, mas não consigo encontrar uma maneira de estruturar a consulta corretamente.

Algo assim é possível com a implementação atual do MySQL JSON?

Respostas:


14

Uma solução fornecida por Morgan Tucker - @morgo é usar da seguinte json_containsforma:

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

Por enquanto, a resposta é boa, mas acredito que possa ter alguns problemas de desempenho e me parecer um pouco tonta (consulte a próxima consulta) - mas vou lidar com eles quando chegar lá :)

Se eu precisasse consultar um intervalo de datas (de 2016-04-24a 2016-04-26), seria necessário adicionar um inválido json_containspara cada dia no período da seguinte maneira:

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 isso retornaria dados inválidos se eu tivesse uma datechave aninhada em outro lugar

Então, se você tem uma solução diferente, eu gostaria de saber


como variante - defina a matriz de profundidade máxima da data - SELECT MAX (json_depth (dados - >> '$ [*]. date')), do que através do loop na extração do procedimento armazenado para as tabelas temporárias - id e data selecionada - selecione id, json_extract ( data, "$ [0] .date") como 'data' dos aplicativos, que não selecione o ID, json_extract ( data, "$ [1] .date") como 'data' dos aplicativos e etc. que aplique todos os filtros e têm lista de ID
a_vlad

você me deu uma pista sobre como usar a sintaxe json_contains
Jimmy Ilenloa
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.