Parse json массивы с использованием HIVE
У меня есть много json-массивов, хранящихся в таблице (jt), которая выглядит так:
[{"ts":1403781896,"id":14,"log":"show"},{"ts":1403781896,"id":14,"log":"start"}]
[{"ts":1403781911,"id":14,"log":"press"},{"ts":1403781911,"id":14,"log":"press"}]
Каждый массив является записью.
Я хотел бы проанализировать эту таблицу, чтобы получить новую таблицу (журналы) с тремя полями: ts, id, log.
Я попытался использовать метод get_json_object, но кажется, что этот метод несовместим с массивами json, потому что я получаю только нулевые значения.
Это код, который я тестировал:
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;
Я пытался использовать другие функции, но они кажутся очень сложными.
Спасибо!:)
Update!
Я решил проблему, выполнив регулярное выражение:
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;
Ответы
Ответ 1
Используйте функцию 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 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)>
где json_array_col - столбец в jt, который содержит ваш массив 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"}"]
Ответ 2
Я просто столкнулся с этой проблемой: массив JSON хранился в виде строки в таблице hive.
Решение немного хакерское и уродливое, но оно работает и не требует сердеров или внешних UDF
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;
Я сломал строки так, чтобы их было немного легче читать.
Я использую substr(), чтобы удалить первый и последний символы, удалив [и]. Затем я использую regex_replace для сопоставления разделителя между записями в массиве json и добавления или изменения разделителя, чтобы быть чем-то уникальным, который затем может быть легко использован с split(), чтобы превратить строку в массив hive объектов json, который затем может использовать с explode(), как описано в предыдущем решении.
Обратите внимание, что используемое здесь разделительное выражение ( "}", ") не будет работать с исходным набором данных... регулярное выражение должно быть (" },\{ "), и тогда замена должна была бы be" },, {" eg..
split(regexp_replace(substr(json_array_col, 2, length(json_array_col)-2),
'"},\\{"', '"},,,,{"'), ',,,,')
Ответ 3
потому что get_json_object не поддерживает строку json array, поэтому вы можете выполнить json-объект, например:
SELECT
get_json_object(concat(concat('{"root":', jt.value), '}'), '$.root')
FROM jt;