2

我必须使用 Apache PIG 将需要组合在一起的文件。第一个文件包含书名列表,就像这样,每个书名都单独一行。

Ted Dunning,  Mahout in Action
Leo Tolstoy,  War and Peace
Douglas Adams, The hitchhiker guide to the galaxy.
James Sununu,  galaxy III for Dummies
Tom McArthur,  The War we went to

第二个文件是单词列表及其 ID。像这样

ted, 12
tom, 13
douglas, 14
galaxy, 15
war, 16
leo, 17
peace, 18

我需要加入这两个文件以产生如下输出:

对于“列夫·托尔斯泰,战争与片断”这句话,它应该产生

17:1,16:1,18:1

对于“汤姆麦克阿瑟,我们参加的战争”这句话,它应该产生

13:1,16:1

换句话说,我需要使用单词作为键来执行连接。到目前为止,我已经在 pig 中编写了以下代码

titles = LOAD 'Titles' AS ( title : chararray );  
termIDs = LOAD  'TermIDs' AS (  term:chararray,id:int);

A = SAMPLE titles 0.01;
X = FOREACH A GENERATE STRSPLIT(title,'[ _\\[\\]\\/,\\.\\(\\)]+');

这给出了加载的两个文件,并且 X 包含 BAGS 列表,每个包包含相应行上出现的术语。像这样:

((ted,dunning,mahout,in,action))
((leo,tolstoy,war,and,peace))

由于周六晚上迟到的原因,如果不编写 UDF 或使用流式传输,我无法弄清楚 JOIN 步骤的方法。是否甚至可以只使用 PIG 原语。

4

1 回答 1

5

您可以将 TOKENIZE 的结果展平,因此所有的包都变成了行,现在您可以使用 termsID 加入 X 关系。

X = foreach A generate title, flatten(TOKENIZE(title)) as term;
J = join X by (term),  termIDs by (term);
G = group J by title;
Result = foreach G generate group as title, termIDs.id;

上面的代码是在我的手机上打的,所以没有调试。

更新 1:

对于最好使用 STRSPLIT 而不是 TOKENIZE 的情况,您可以结合使用 FLATTEN 和 TOBAG 来实现与 TOKENIZE 相同的效果,即从 STRSPLIT 返回的元组中获取单词包。

SPLT = foreach A generate title, FLATTEN(STRSPLIT(title,'[ _\\[\\]\\/,\\.\\(\\)]+'));
X_tmp = foreach SPLT generate $0 as title, FLATTEN(TOBAG($1..$20)) as term; -- pivots the row
X = filter X_tmp by term is not null; -- this removes the extra bag rows when title was split in less than 20 terms
J = join X by (term),  termIDs by (term) using 'replicated';
G = group J by title;
Result = foreach G generate group as title, termIDs.id;

如果任何标题超过 20 个术语,则增加 TOBAG 中的数量。

于 2012-09-24T15:57:53.243 回答