在apache pig中将键值元组包转换为Map

drnojrws  于 2021-06-24  发布在  Pig
关注(0)|答案(2)|浏览(438)

我对pig很陌生,我想把一包元组转换成一个Map,每个元组中都有特定的值作为键。基本上我想改变: {(id1, value1),(id2, value2), ...} 进入 [id1#value1, id2#value2] 我在网上找了一段时间,但似乎找不到解决办法。我试过:

  1. bigQMap = FOREACH bigQFields GENERATE TOMAP(queryId, queryStart);

但我最终得到了一袋Map(例如。 {[id1#value1], [id2#value2], ...} ),这不是我想要的。如何从一袋键值元组中建立一个Map?
下面是我试图运行的特定脚本,以防相关

  1. rawlines = LOAD '...' USING PigStorage('`');
  2. bigQFields = FOREACH bigQLogs GENERATE GFV(*,'queryId')
  3. as queryId, GFV(*, 'queryStart')
  4. as queryStart;
  5. bigQMap = ?? how to make a map with queryId as key and queryStart as value ?? ;
u2nhd7ah

u2nhd7ah1#

TOMAP 获取一系列对并将它们转换为Map,因此它的用法如下:

  1. -- Schema: A:{foo:chararray, bar:int, bing:chararray, bang:int}
  2. -- Data: (John, 27, Joe, 30)
  3. B = FOREACH A GENERATE TOMAP(foo, bar, bing, bang) AS m ;
  4. -- Schema: B:{m: map[]}
  5. -- Data: (John#27,Joe#30)

因此,正如您所见,语法不支持将包转换为Map。据我所知,没有办法将一个包转换成你必须在纯PigMap的格式。但是,您可以明确地编写一个javaudf来实现这一点。
注意:我对java不是很有经验,所以这个udf可以很容易地改进(添加异常处理,如果一个键添加两次会发生什么等等)。然而,它确实完成了你所需要的。

  1. package myudfs;
  2. import java.io.IOException;
  3. import org.apache.pig.EvalFunc;
  4. import java.util.Map;
  5. import java.util.HashMap;
  6. import java.util.Iterator;
  7. import org.apache.pig.data.Tuple;
  8. import org.apache.pig.data.DataBag;
  9. public class ConvertToMap extends EvalFunc<Map>
  10. {
  11. public Map exec(Tuple input) throws IOException {
  12. DataBag values = (DataBag)input.get(0);
  13. Map<Object, Object> m = new HashMap<Object, Object>();
  14. for (Iterator<Tuple> it = values.iterator(); it.hasNext();) {
  15. Tuple t = it.next();
  16. m.put(t.get(0), t.get(1));
  17. }
  18. return m;
  19. }
  20. }

一旦将脚本编译到jar中,就可以像这样使用它:

  1. REGISTER myudfs.jar ;
  2. -- A is loading some sample data I made
  3. A = LOAD 'foo.in' AS (foo:{T:(id:chararray, value:chararray)}) ;
  4. B = FOREACH A GENERATE myudfs.ConvertToMap(foo) AS bar;

的内容 foo.in :

  1. {(open,apache),(apache,hadoop)}
  2. {(foo,bar),(bar,foo),(open,what)}

输出自 B :

  1. ([open#apache,apache#hadoop])
  2. ([bar#foo,open#what,foo#bar])

另一种方法是使用python创建udf:

我的自定义项.py

  1. # !/usr/bin/python
  2. @outputSchema("foo:map[]")
  3. def BagtoMap(bag):
  4. d = {}
  5. for key, value in bag:
  6. d[key] = value
  7. return d

用法如下:

  1. Register 'myudfs.py' using jython as myfuncs;
  2. -- A is still just loading some of my test data
  3. A = LOAD 'foo.in' AS (foo:{T:(key:chararray, value:chararray)}) ;
  4. B = FOREACH A GENERATE myfuncs.BagtoMap(foo) ;

并生成与javaudf相同的输出。
优点:因为我不太喜欢Map,这里有一个链接解释了如何用键值对复制Map的功能。因为您的键值对在一个包中,所以您需要在嵌套的 FOREACH :

  1. -- A is a schema that contains kv_pairs, a bag in the form {(id, value)}
  2. B = FOREACH A {
  3. temp = FOREACH kv_pairs GENERATE (key=='foo'?value:NULL) ;
  4. -- Output is like: ({(),(thevalue),(),()})
  5. -- MAX will pull the maximum value from the filtered bag, which is
  6. -- value (the chararray) if the key matched. Otherwise it will return NULL.
  7. GENERATE MAX(temp) as kv_pairs_filtered ;
  8. }
展开查看全部
ma8fv8wu

ma8fv8wu2#

我遇到了同样的情况,所以我提交了一个刚刚被接受的补丁:https://issues.apache.org/jira/browse/pig-4638
这意味着你想要的是一个核心部分,从pig0.16开始。

相关问题