Большинство Pig учебники вы найдете предположите , что вы работаете с данными , где вы знаете имена всех столбцов заранее, а сами имена столбцов просто ярлыки, против того композитов меток и данных. Например, при работе с HBase на самом деле нередко оба эти предположения ложны. Будучи столбчатой базой данных, очень распространено работать со строками, имеющими тысячи столбцов . При таких обстоятельствах также часто имена столбцов кодируются в измерения, такие как дата и тип счетчика .
Как вы решаете это несоответствие? Если вы находитесь на ранних этапах разработки схемы, вы можете пересмотреть более рядовой подход. Однако, если вам нужно работать с существующей схемой, вы можете это сделать с помощью пользовательских функций Pig .
Скажем, у нас есть следующая таблица:
RowKey | cf1: 20130101post | cf1: 20130101comment | cf1: 20130101like | cf1: 20130102post | … |
---|---|---|---|---|---|
ce410-00005031-00089182 | 147 | 5 | 41 | 153 | |
ce410-00005031-00021915 | 1894 | 33 | 86 | 1945 | |
5faa4-00009521-00019828 | 30 | 2 | 8 | 31 | |
… |
Здесь есть составной ключ строки, но также составные ключи столбца. Поскольку дата является частью ключей столбцов, потенциально существует много, много столбцов. Перечислять их все в своих сценариях Свинья непрактично. Обратите внимание, что они также находятся в одном семействе столбцов. Чтобы загрузить их все, вы можете сделать следующее в Pig:
data = load 'hbase://table_name' using org.apache.pig.backend.hadoop.hbase.HBaseStorage('cf1:*', '-loadKey true') AS (id:chararray, stats:map[int]); illustrate data;
Это приведет к тому, что все столбцы будут загружены в карту Pig , которая является просто набором кортежей:
----------------------------------------------------------------------------------------------------- | data | id:chararray | stats:map(:int) | ----------------------------------------------------------------------------------------------------- | | ce410-00005031-00089182 | {20130101post=147,20130101comment=5,20130101like=41,...} | -----------------------------------------------------------------------------------------------------
Итак, теперь вы загрузили все данные, но как вам разобрать имена столбцов в их соответствующие части, чтобы можно было применить логику к значениям? Вот очень простая реализация UDF на Python, которая превратит эту карту в пакет:
@outputSchema("values:bag{t:tuple(key, value)}") def bag_of_tuples(map_dict): return map_dict.items()
Вы можете включить этот UDF (поместите вышеупомянутое в файл с именем udfs.py в текущем рабочем каталоге для pig) и вызовите его так:
register 'udfs.py' using jython as py data = load 'hbase://table_name' using org.apache.pig.backend.hadoop.hbase.HBaseStorage('cf1:*', '-loadKey true') AS (id:chararray, stats:map[int]); databag = foreach data generate id, FLATTEN(py.bag_of_tuples(stats)); illustrate databag;
Это использует встроенный оператор FLATTEN , который берет сумку и делает перекрестное произведение с рядом сумок, чтобы получить N новых рядов.
------------------------------------------------------------------------------ | databag | id:chararray | key:bytearray | value:bytearray | ------------------------------------------------------------------------------ | | ce410-00005031-00089182 | 20130101post | 147 | ------------------------------------------------------------------------------ | | ce410-00005031-00089182 | 20130101comment | 5 | ------------------------------------------------------------------------------ | | ce410-00005031-00089182 | 20130101like | 41 | ------------------------------------------------------------------------------
Затем вы можете обработать ваши данные как обычно. Затем вы можете записать свой пакет данных в HBase в том же формате, используя встроенный UDF- файл TOMAP и тот же * синтаксис. Предполагая, что вы создали новые имена и значения столбцов в вашем скрипте, вы можете сделать:
... mapped = foreach processed_data generate TOMAP(columnname, value) as stats; store mapped into 'hbase://table_name' using org.apache.pig.backend.hadoop.hbase.HBaseStorage('stats:*');