Подтвердить что ты не робот

Как я могу использовать тип данных карты в 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.

Является ли тип карты свиньи полупеченным? Что мне не хватает?

4b9b3361

Ответ 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;