J'ai de nombreux tableaux json stockés dans une table (jt) qui ressemble à ceci:
[{"ts":1403781896,"id":14,"log":"show"},{"ts":1403781896,"id":14,"log":"start"}]
[{"ts":1403781911,"id":14,"log":"press"},{"ts":1403781911,"id":14,"log":"press"}]
Chaque tableau est un enregistrement.
Je voudrais analyser cette table afin d'obtenir une nouvelle table (logs) avec 3 champs: ts, id, log. J'ai essayé d'utiliser la méthode get_json_object, mais il semble que cette méthode ne soit pas compatible avec les tableaux json car je n'obtiens que des valeurs nulles.
Voici le code que j'ai testé:
CREATE TABLE logs AS
SELECT get_json_object(jt.value, '$.ts') AS ts,
get_json_object(jt.value, '$.id') AS id,
get_json_object(jt.value, '$.log') AS log
FROM jt;
J'ai essayé d'utiliser d'autres fonctions mais elles semblent vraiment compliquées. Je vous remercie! :)
Mise à jour! J'ai résolu mon problème en effectuant une expression rationnelle:
CREATE TABLE jt_reg AS
select regexp_replace(regexp_replace(value,'\\}\\,\\{','\\}\\\n\\{'),'\\[|\\]','') as valuereg from jt;
CREATE TABLE logs AS
SELECT get_json_object(jt_reg.valuereg, '$.ts') AS ts,
get_json_object(jt_reg.valuereg, '$.id') AS id,
get_json_object(jt_reg.valuereg, '$.log') AS log
FROM ams_json_reg;
Utilisez fonction explode ()
Hive (default)> CREATE TABLE logs AS
> SELECT get_json_object(single_json_table.single_json, '$.ts') AS ts,
> get_json_object(single_json_table.single_json, '$.id') AS id,
> get_json_object(single_json_table.single_json, '$.log') AS log
> FROM
> (SELECT explode(json_array_col) as single_json FROM jt) single_json_table ;
Automatically selecting local only mode for query
Total MapReduce jobs = 3
Launching Job 1 out of 3
Number of reduce tasks is set to 0 since there's no reduce operator
Hive (default)> select * from logs;
OK
ts id log
1403781896 14 show
1403781896 14 start
1403781911 14 press
1403781911 14 press
Time taken: 0.118 seconds, Fetched: 4 row(s)
Hive (default)>
où json_array_col est la colonne de jt qui contient votre tableau de jsons.
Hive (default)> select json_array_col from jt;
json_array_col
["{"ts":1403781896,"id":14,"log":"show"}","{"ts":1403781896,"id":14,"log":"start"}"]
["{"ts":1403781911,"id":14,"log":"press"}","{"ts":1403781911,"id":14,"log":"press"}"]
parce que get_json_object ne prend pas en charge la chaîne de tableau json, vous pouvez donc concaténer un objet json, comme ceci:
SELECT
get_json_object(concat(concat('{"root":', jt.value), '}'), '$.root')
FROM jt;
Je viens de rencontrer ce problème, avec le tableau JSON stocké sous forme de chaîne dans la table Hive.
La solution est un peu hacky et moche, mais elle fonctionne et ne nécessite pas de serdes ou d'UDF externes
SELECT
get_json_object(single_json_table.single_json, '$.ts') AS ts,
get_json_object(single_json_table.single_json, '$.id') AS id,
get_json_object(single_json_table.single_json, '$.log') AS log
FROM ( SELECT explode (
split(regexp_replace(substr(json_array_col, 2, length(json_array_col)-2),
'"}","', '"}",,,,"'), ',,,,')
) FROM src_table) single_json_table;
J'ai rompu les lignes pour que ce soit un peu plus facile à lire. J'utilise substr () pour supprimer les premier et dernier caractères, en supprimant [et]. J'utilise ensuite regex_replace pour faire correspondre le séparateur entre les enregistrements du tableau json et j'ajoute ou modifie le séparateur pour qu'il soit quelque chose d'unique qui peut ensuite être utilisé facilement avec split () pour transformer la chaîne en un tableau Hive d'objets json qui peut ensuite être utilisé avec explode () comme décrit dans la solution précédente.
Remarque, l'expression rationnelle de séparation utilisée ici ("}", ") ne fonctionnerait pas avec l'ensemble de données d'origine ... l'expression rationnelle devrait être ("},\{") et le remplacement devrait alors être"} ,{" par exemple..
split(regexp_replace(substr(json_array_col, 2, length(json_array_col)-2),
'"},\\{"', '"},,,,{"'), ',,,,')