web-dev-qa-db-ja.com

Apache Pigでマップデータ型を使用するにはどうすればよいですか?

Apache Pigを使用して、大きなキー->値のマッピングを作成し、マップで検索して、キーを反復処理したいと思います。ただし、これらのことを行うための構文すら存在しないようです。マニュアル、ウィキ、サンプルコード、エレファントブック、グーグルをチェックし、パーサーソースを解析してみました。すべての例は、ファイルからマップリテラルをロードします...そしてそれらを使用することはありません。 Pigのマップをどのように使用できますか?

まず、2列のCSVファイルをマップに直接ロードする方法がないようです。単純なmap.csvがある場合:

1,2
3,4
5,6

そして、私はそれを地図としてロードしようとします:

m = load 'map.csv' using PigStorage(',') as (M: []);
dump m;

空のタプルが3つあります。

()
()
()

そこで、タプルをロードしてからマップを生成しようとします。

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])。

OK、それで私は自分の地図をmap.pigのように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[ ]}

うーん、わかりました。おそらく2つの関係があるため、結合が必要です。

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.

Pigのマップタイプは中途半端ですか?何が足りないのですか?

21

現在、pigマップには、文字列を含む変数ではなく、指定したchararray(文字列)へのキーが必要です。したがって、map#keyでは、キーは指定する定数文字列である必要があります(例:map# 'keyvalue')。

これの典型的な使用例は、要素の1つがキーと値のペアである複雑なデータ構造をロードし、後でforeachステートメントで、関心のあるキーに基づいて特定の値を参照できるようにすることです。

http://pig.Apache.org/docs/r0.9.1/basic.html#map-schema

2
jayadev

Pigバージョン0.10.0には、奇数を変換する「TOMAP」( http://pig.Apache.org/docs/r0.10.0/func.html#tomap )と呼ばれる新しい関数があります。 (chararray)キーへのパラメーター、さらには値へのパラメーター。残念ながら、私は通常、さまざまな長さとキーの任意のdictを処理するため、これがそれほど有用であるとは思いませんでした。

可変数のパラメーターではなく、単一の引数としてタプルを使用するTOMAP関数の方がはるかに便利であることがわかります。

これは問題の完全な解決策ではありませんが、TOMAPが利用できることで、実際の解決策を構築するためのオプションがさらにいくつか提供されます。

1
John Prior

素晴らしい質問です!私は個人的にPigのマップが好きではありません。これらは、Java、C#などの従来のプログラミング言語で使用されており、マップ内のキーを検索するのに非常に便利で高速です。一方、Pigのマップの機能は非常に限られています。

あなたが正しく指摘したように、Pigのマップで変数キーを検索することはできません。キーは定数である必要があります。例えばmyMap# 'keyFoo'は許可されていますが、myMap#$ SOME_VARIABLEは許可されていません。

あなたがそれについて考えるならば、あなたは豚の地図を必要としません。通常、あるソースからデータをロードし、変換し、他のデータセットと結合し、フィルタリングし、変換します。 JOINは、実際にはデータ内の変数キーを検索するのに適しています。例えばdata1には2つの列AとBがあり、data2には3つの列X、Y、Zがあります。data1BYAとdata2 BY Zを結合すると、JOINは列Zの値を列B(列A経​​由)。したがって、data1は基本的にマップA-> Bを表します。

では、なぜPigでMapが必要なのですか?

通常、Hadoopデータは、従来の言語のさまざまなデータソースのダンプです。元のデータソースにマップが含まれている場合、HDFSデータには対応するマップが含まれます。

マップデータをどのように処理できますか?

実際には2つのユースケースがあります。

  1. マップキーは定数です。例えばHttpRequestヘッダーデータには、マップのキーとして時間、サーバー、clientIpが含まれています。特定のキーの値にアクセスするには、定数キーを使用してそれらにアクセスする場合があります。例えばheader# 'clientIp'。

  2. マップキーは変数です。このような場合、マップキーを他のデータセットと結合することをお勧めします。私は通常、UDFを使用してマップをバッグに変換します MapToBag、マップデータを2つのフィールドタプル(キー、値)のバッグに変換します。マップデータがBagof tuplesに変換されると、他のデータセットと簡単に結合できます。

これがお役に立てば幸いです。

1
Gaurav Phapale

1)マップデータをロードする場合は、「[programming#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)} | [programming#SQL、rdbms#Oracle] 4567 | [email protected] |(first_name_4567、 middle_initial_4567、last_name_4567)| {(project_4567_1)、(project_4567_2)、(project_4567_3)} | [programming#Java、OS#Linux]


私のスキーマ:

a = LOAD'pigtest.csv 'using PigStorage(' | ')AS(employee_id:int、email:chararray、name:Tuple(first_name:chararray、middle_name:chararray、last_name:chararray)、project_list:bag {project:Tuple( project_name:chararray)}、skills:map [chararray]);

b = FOREACH a GENERATE employee_id、email、name.first_name、project_list、skills# 'programming';

ダンプb;

1
y durga prasad

任意のデータをロードしてから、変換してキー値形式で保存し、後で使用するために読み取ることができます。

data = load 'somedata.csv' using PigStorage(',')
STORE data into 'folder' using PigStorage('#')

次に、マップされたデータとして読み取ります。

0
Shahir Ansari

relations の観点から考える必要があると思います。 map は1つのレコードの1つのフィールドにすぎません。次に、2つのセットdataを結合するなど、リレーションにいくつかの 操作 を適用できます。 )マッピング

入力

$ 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

0
Romain