Извлечение массива структур в Hive

У меня есть внешняя таблица в улье

CREATE EXTERNAL TABLE FOO (  
  TS string,  
  customerId string,  
  products array< struct <productCategory:string, productId:string> >  
)  
PARTITIONED BY (ds string)  
ROW FORMAT SERDE 'some.serde'  
WITH SERDEPROPERTIES ('error.ignore'='true')  
LOCATION 'some_locations'  
;

Запись таблицы может содержать такие данные, как:

1340321132000, 'some_company', [{"productCategory":"footwear","productId":"nik3756"},{"productCategory":"eyewear","productId":"oak2449"}]

Кто-нибудь знает, есть ли способ просто извлечь всю productCategory из этой записи и вернуть ее в виде массива productCategories без использования взрыва. Что-то вроде следующего:

["footwear", "eyewear"] 

Или мне нужно написать свой собственный GenericUDF, если да, я не очень хорошо знаю Java (человек Ruby), может кто-нибудь дать мне несколько советов? Я прочитал несколько инструкций по UDF от Apache Hive. Однако я не знаю, какой тип коллекции лучше всего подходит для обработки массива и какой тип коллекции для обработки структур?

===

Я несколько ответил на этот вопрос, написав GenericUDF, но столкнулся с двумя другими проблемами. Именно в этом SO Question


person pchu    schedule 26.03.2013    source источник


Ответы (3)


Вы можете использовать json serde или встроенные функции get_json_object, json_tuple.

С Hive-JSON SerDe от rcongiu использование будет следующим:

определить таблицу:

CREATE TABLE complex_json (
DocId string,
Orders array<struct<ItemId:int, OrderDate:string>>)

загрузите в него образец json (важно, чтобы эти данные были однострочными):

{"DocId":"ABC","Orders":[{"ItemId":1111,"OrderDate":"11/11/2012"},{"ItemId":2222,"OrderDate":"12/12/2012"}]}

Затем получить идентификаторы заказов так же просто, как:

SELECT Orders.ItemId FROM complex_json LIMIT 100;

Он вернет вам список идентификаторов:

ИД [1111,2222]

Доказано, что он возвращает правильные результаты в моей среде. Полный список:

add jar hdfs:///tmp/json-serde-1.3.6.jar;

CREATE TABLE complex_json (
  DocId string,
  Orders array<struct<ItemId:int, OrderDate:string>>
)
ROW FORMAT SERDE 'org.openx.data.jsonserde.JsonSerDe';

LOAD DATA INPATH '/tmp/test.json' OVERWRITE INTO TABLE complex_json;

SELECT Orders.ItemId FROM complex_json LIMIT 100;

Подробнее здесь:

http://thornydev.blogspot.com/2013/07/querying-json-records-via-hive.html

person Viktor    schedule 29.02.2016

Один из способов — использовать функции inline или explode, например:

SELECT 
    TS,
    customerId,
    pCat,
    pId,
FROM FOO 
LATERAL VIEW inline(products) p AS pCat, pId

В противном случае вы можете написать UDF. Ознакомьтесь с этим сообщением и этот пост для этого. Наряду со следующими ресурсами:

person dstandish    schedule 29.02.2016

Если размер массива фиксирован (например, 2). Пожалуйста, попробуй:

products[0].productCategory,products[1].productCategory

Но если нет, UDF должен быть правильным решением. Я думаю, что вы могли бы сделать это в JRuby. ГЛ!

person www    schedule 26.03.2013
comment
Спасибо, но размер массива не фиксирован. Хотя хорошая идея использовать JRuby, для этого нужно использовать Java для написания GenericUDF. Хуже того, в написании GenericUDF не так много ссылок. - person pchu; 26.03.2013