Как я могу использовать тип данных карты в Apache Pig?
Я хотел бы использовать Apache Pig для создания большого значения ключа → значения, просматривать вещи на карте и перебирать ключи. Однако даже не кажется синтаксисом для выполнения этих действий; Я проверил руководство, вики, образец кода, книгу Elephant, Google и даже попытался разобрать источник парсера. Каждый пример загружает картографические литералы из файла... и никогда не использует их. Как вы можете использовать карты Pig?
Во-первых, похоже, что нет возможности загрузить файл с двумя столбцами CSV на карту напрямую. Если у меня есть простой map.csv
:
1,2
3,4
5,6
И я пытаюсь загрузить его как карту:
m = load 'map.csv' using PigStorage(',') as (M: []);
dump m;
Я получаю три пустых набора:
()
()
()
Итак, я пытаюсь загрузить кортежи и затем сгенерировать карту:
m = load 'map.csv' using PigStorage(',') as (key:chararray, val:chararray);
b = foreach m generate [key#val];
ERROR 1000: Error during parsing. Encountered " "[" "[ "" at line 1, column 24.
...
Многие вариации синтаксиса также терпят неудачу (например, generate [$0#$1]
).
ОК, поэтому я превращаю свою карту в формат буквенного обозначения Pig как map.pig
:
[1#2]
[3#4]
[5#6]
И загрузите его:
m = load 'map.pig' as (M: []);
Теперь загрузите несколько ключей и попробуйте найти:
k = load 'keys.csv' as (key);
dump k;
3
5
1
c = foreach k generate m#key; /* Or m[key], or... what? */
ERROR 1000: Error during parsing. Invalid alias: m in {M: map[ ]}
Hrm, хорошо, возможно, поскольку есть два отношения, нам нужно соединение:
c = join k by key, m by /* ...um, what? */ $0;
dump c;
ERROR 1068: Using Map as key not supported.
c = join k by key, m by m#key;
dump c;
Error 1000: Error during parsing. Invalid alias: m in {M: map[ ]}
нормально. Как я могу ссылаться на ключ (или значение) карты? Синтаксис схемы карты не означает, что вы даже называете ключ и значение (в списке рассылки указывается, что нет способа назначить типы).
Наконец, я просто хотел бы найти все ключи на моей карте:
d = foreach m generate ...oh, forget it.
Является ли тип карты свиньи полупеченным? Что мне не хватает?
Ответы
Ответ 1
В настоящее время карты свиней нуждаются в ключом к chararray (string), который вы поставляете, а не переменная, содержащая строку. поэтому в map # key ключ должен быть постоянной строкой, которую вы поставляете (например: map # 'keyvalue').
Типичный пример использования заключается в загрузке сложной структуры данных, когда один из элементов является ключевой парой значений, а затем в инструкции foreach вы можете ссылаться на конкретное значение на основе интересующего вас ключа.
http://pig.apache.org/docs/r0.9.1/basic.html#map-schema
Ответ 2
В версии Pig 0.10.0 есть новая функция, доступная под названием "TOMAP" (http://pig.apache.org/docs/r0.10.0/func.html#tomap), которая преобразует ее нечетную (chararray) параметры для ключей и даже параметры для значений. К сожалению, я не нашел его полезным, хотя, поскольку я обычно имею дело с произвольными dicts разной длины и ключей.
Я бы нашел функцию TOMAP, которая взяла кортеж как один аргумент, а не переменное число параметров, чтобы быть намного полезнее.
Это не полное решение вашей проблемы, но наличие TOMAP дает вам еще несколько вариантов для вашего построения реального решения.
Ответ 3
Отличный вопрос!
Мне лично не нравятся Карты в Свинье. У них есть место в традиционных языках программирования, таких как Java, С# и т.д., Где его очень удобно и быстро найти ключ на карте. С другой стороны, Maps in Pig имеют очень ограниченные возможности.
Как вы правильно указали, невозможно найти ключевой ключ в Map на Pig. Ключ должен быть постоянным. например myMap # 'keyFoo' разрешен, но myMap # $SOME_VARIABLE не разрешен.
Если вы думаете об этом, вам не нужна карта в Pig. Обычно обычно загружаются данные из какого-то источника, преобразуются, объединяются с другим набором данных, фильтруются, преобразуются и т.д. JOIN действительно хорошо просматривает переменные ключи в данных.
например data1 имеет 2 столбца A и B, а data2 имеет 3 столбца X, Y, Z. Если вы присоединяетесь к data1 BY A с data2 BY Z, JOIN выполняет работу карты (от традиционного языка), которая отображает значение столбца Z в значение столбец B (через столбец A). Таким образом, data1 по существу представляет карту A → B.
Итак, зачем нам Map в Pig?
Обычно данные Hadoop являются дампами разных источников данных из традиционных языков. Если исходные источники данных содержат Карты, данные HDFS будут содержать соответствующую карту.
Как можно обрабатывать данные Карты?
Есть действительно 2 варианта использования:
-
Ключи карты - это константы.
например Данные заголовка HttpRequest содержат время, сервер, clientIp в качестве ключей в Map. для доступа к значению определенного ключа, в одном случае доступ к ним осуществляется с помощью ключа Constant.
например HEADER # 'ClientIP'.
-
Ключами карты являются переменные.
В этих случаях вы, скорее всего, захотите присоединиться к клавишам карты с некоторым другим набором данных. Я обычно конвертирую карту в сумку с помощью UDF MapToBag, которая преобразует данные карты в сумку из 2 наборов полей (ключ, значение). Когда данные карты преобразуются в сумку кортежей, ее легко присоединить к другим наборам данных.
Надеюсь, это поможет.
Ответ 4
Думаю, вам нужно подумать в терминах relations и map - это всего лишь одно поле одной записи. Затем вы можете применить некоторые операции в отношении отношений, например, объединение двух наборов данных и отображения:
Ввод
$ cat data.txt
1
2
3
4
5
$ cat mapping.txt
1 2
2 4
3 6
4 8
5 10
Свиньи
mapping = LOAD 'mapping.txt' AS (key:CHARARRAY, value:CHARARRAY);
data = LOAD 'data.txt' AS (value:CHARARRAY);
-- list keys
mapping_keys =
FOREACH mapping
GENERATE key;
DUMP mapping_keys;
-- join mapping to data
mapped_data =
JOIN mapping BY key, data BY value;
DUMP mapped_data;
Выход
> # keys
(1)
(2)
(3)
(4)
(5)
> # mapped data
(1,2,1)
(2,4,2)
(3,6,3)
(4,8,4)
(5,10,5)
Этот ответ также может помочь вам, если вы просто хотите сделать простой поиск:
pass-a-relation-to-a-pig-udf-when-using-foreach-on-another-relation
Ответ 5
1) Если вы хотите загрузить данные карты, это должно быть как "[программирование # SQL, rdbms # Oracle]"
2) Если вы хотите загрузить данные кортежа, это должно быть как "(first_name_1234, middle_initial_1234, last_name_1234)"
3) Если вы хотите загрузить данные пакета, это должно быть как "{(project_4567_1), (project_4567_2), (project_4567_3)}"
мой файл pigtest.csv как этот
1234 | [email protected] | (first_name_1234, middle_initial_1234, last_name_1234) | {(project_1234_1), (project_1234_2), (project_1234_3)} | [программирование # SQL, СУБД Oracle #]
4567 | [email protected] | (first_name_4567, middle_initial_4567, last_name_4567) | {(project_4567_1), (project_4567_2), (project_4567_3)} | [программирование # Java, ОС Linux #]
моя схема:
a = LOAD 'pigtest.csv', используя PigStorage ('|') AS (employee_id: int, email: chararray, name: tuple (first_name: chararray, middle_name: chararray, last_name: chararray), project_list: bag {project: tuple (имя_проекта: chararray)}, навыки: map [chararray]);
b = НАПРАВИТЬ GENERATE employee_id, email, name.first_name, project_list, навыки # 'programming';
dump b;