Map 将键值元组包转换为ApachePig中的映射

Map 将键值元组包转换为ApachePig中的映射,map,apache-pig,Map,Apache Pig,我对Pig是新手,我想将一包元组转换成一个映射,每个元组中的特定值作为键。基本上我想改变: {(id1,value1),(id2,value2),…}转换为[id1#value1,id2#value2] 我在网上找了一段时间,但似乎找不到解决办法。我试过: bigQMap = FOREACH bigQFields GENERATE TOMAP(queryId, queryStart); 但我最终得到了一袋地图(例如,{[id1#value1],[id2#value2],…}),这不是我想要的。

我对Pig是新手,我想将一包元组转换成一个映射,每个元组中的特定值作为键。基本上我想改变:

{(id1,value1),(id2,value2),…}
转换为
[id1#value1,id2#value2]

我在网上找了一段时间,但似乎找不到解决办法。我试过:

bigQMap = FOREACH bigQFields GENERATE TOMAP(queryId, queryStart);
但我最终得到了一袋地图(例如,
{[id1#value1],[id2#value2],…}
),这不是我想要的。我如何用一袋键值元组构建地图

下面是我试图运行的特定脚本,以防相关

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

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

-- Schema: A:{foo:chararray, bar:int, bing:chararray, bang:int}
-- Data:     (John,          27,      Joe,            30)
B = FOREACH A GENERATE TOMAP(foo, bar, bing, bang) AS m ;
-- Schema: B:{m: map[]}
-- Data:     (John#27,Joe#30)
REGISTER myudfs.jar ;
-- A is loading some sample data I made
A = LOAD 'foo.in' AS (foo:{T:(id:chararray, value:chararray)}) ;
B = FOREACH A GENERATE myudfs.ConvertToMap(foo) AS bar;
因此,正如您所看到的,语法不支持将包转换为地图。据我所知,没有办法将一个包转换成你必须在纯猪中映射的格式。但是,您可以明确地编写一个函数来完成此操作

注意:我对java不是很有经验,因此可以很容易地改进这个UDF(添加异常处理,如果一个键添加两次会发生什么情况等等)。然而,它确实完成了您所需要的

package myudfs;
import java.io.IOException;
import org.apache.pig.EvalFunc;

import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import org.apache.pig.data.Tuple;
import org.apache.pig.data.DataBag;

public class ConvertToMap extends EvalFunc<Map>
{
    public Map exec(Tuple input) throws IOException {
        DataBag values = (DataBag)input.get(0);
        Map<Object, Object> m = new HashMap<Object, Object>();
        for (Iterator<Tuple> it = values.iterator(); it.hasNext();) {
            Tuple t = it.next();
            m.put(t.get(0), t.get(1));
        }
        return m;
    }
}
foo.in的内容

{(open,apache),(apache,hadoop)}
{(foo,bar),(bar,foo),(open,what)}
B
输出:

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

另一种方法是使用:

myudfs.py 它是这样使用的:

Register 'myudfs.py' using jython as myfuncs;
-- A is still just loading some of my test data
A = LOAD 'foo.in' AS (foo:{T:(key:chararray, value:chararray)}) ;
B = FOREACH A GENERATE myfuncs.BagtoMap(foo) ;
并生成与JavaUDF相同的输出


奖金: 因为我不太喜欢地图,所以有一个链接解释了如何仅使用键值对复制地图的功能。由于键值对在一个包中,因此需要在嵌套的
FOREACH
中执行类似映射的操作:

-- A is a schema that contains kv_pairs, a bag in the form {(id, value)}
B = FOREACH A {
    temp = FOREACH kv_pairs GENERATE (key=='foo'?value:NULL) ;
    -- Output is like: ({(),(thevalue),(),()})

    -- MAX will pull the maximum value from the filtered bag, which is 
    -- value (the chararray) if the key matched. Otherwise it will return NULL.
    GENERATE MAX(temp) as kv_pairs_filtered ;
}

我遇到了同样的情况,所以我提交了一个刚刚被接受的补丁:


这意味着你想要的是一个从pig 0.16开始的核心部分。

我以前从未见过
GFV
函数,所以我不确定它输出的是什么,但是
{(id1,value1),(id2,value2),…}
bigQFields
的结果模式的一部分吗?实际上,你只是发布bigQFields的模式,因为这就是你想要转换成地图的东西,对吗?是的
GFV
只是我使用的一个UDF。正如你所知:我只是提出了对现有Pig-TOMAP函数的一个增强:嗯,奖金部分看起来很容易实现,但这不是比仅仅使用地图效率低得多吗?是的,但我不确定有多少。但对于效率上的损失,你可以在灵活性上弥补。您可以同时提取键和值,一次提取多个值,
flant
it,在行中使用变量而不是带引号的字符串来获取值等,同时避免编写任何Java(这可能是一个加号,也可能不是加号,取决于您对Java的喜爱程度)。@Penguinator,如果我必须将包转换为地图,那么我会使用python UDF(我刚刚更新了我的答案以包含一个示例)。+1这很好。我认为映射在概念上更好,但我不想在jar上创建依赖项。
-- A is a schema that contains kv_pairs, a bag in the form {(id, value)}
B = FOREACH A {
    temp = FOREACH kv_pairs GENERATE (key=='foo'?value:NULL) ;
    -- Output is like: ({(),(thevalue),(),()})

    -- MAX will pull the maximum value from the filtered bag, which is 
    -- value (the chararray) if the key matched. Otherwise it will return NULL.
    GENERATE MAX(temp) as kv_pairs_filtered ;
}