PigLatin 映射键值

Posted

技术标签:

【中文标题】PigLatin 映射键值【英文标题】:PigLatin map key value 【发布时间】:2012-06-08 15:46:21 【问题描述】:

我第一次使用一些 PigLatin 代码,并希望能够通过首先将键值生成为 chararray,然后使用该键来访问映射中的值。例如,categoryIds 是我的地图,

catIds = foreach filteredContexts generate elementId,SUBSTRING(categoryAndConfidence,0,2) as catId;
categoryNames = foreach catIds generate elementId, categoryIds#catId as catName;

这是我收到的错误: ERROR 1000:解析时出错。在第 28 行第 64 列遇到“”catId“”。 期待其中之一: “空值” ... ... ... “空” ...

我试图做的事情是不可能的吗?每次使用地图时是否需要明确说明键值(例如:categoryIds#'51')?

【问题讨论】:

【参考方案1】:

据我所知,Pig 没有提供任何内置方法来从地图中获取密钥。对于 map 字段,只能使用 SIZE 函数获取其大小,使用 IsEmpty 函数检查是否为空,或者使用 map_field#'key' 查找给定键的值。

我自己编写了一些 UDF 来帮助我更好地处理地图数据类型。我的一个功能可能对您有用 - MapToBag - 它可以将地图:map[value_type] 转换为包:bag:tuple(key:chararray, value:value_type)。有了包,既可以拿到钥匙,也可以进行FLATTEN操作。

package com.XXX.YYY.ZZZ;

import org.apache.pig.EvalFunc;
import org.apache.pig.FuncSpec;
import org.apache.pig.data.*;
import org.apache.pig.impl.logicalLayer.FrontendException;
import org.apache.pig.impl.logicalLayer.schema.Schema;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

public class MapToBag extends EvalFunc<DataBag> 

    @Override
    public DataBag exec(Tuple input) throws IOException 
        if (input == null || input.size() == 0) 
            return null;
        

        @SuppressWarnings("unchecked")
        Map<String, Object> map = (Map<String, Object>) input.get(0);
        if (map == null || map.isEmpty()) 
            return null;
        

        DataBag bag = bagFactory.newDefaultBag();
        for (String key : map.keySet()) 
            Object value = map.get(key);
            Tuple oneKeyTuple = tupleFactory.newTuple(2);
            oneKeyTuple.set(0, key);
            oneKeyTuple.set(1, value);
            bag.add(oneKeyTuple);
        

        return (bag.size() == 0) ? null : bag;
    

    @Override
    public Schema outputSchema(Schema input) 
        try 
            Schema innerSchema = new Schema();
            innerSchema.add(new Schema.FieldSchema("key", DataType.CHARARRAY));
            innerSchema.add(getMapValueSchema(input));
            Schema tupleSchema = new Schema(new Schema.FieldSchema(null, innerSchema, DataType.TUPLE));
            return new Schema(new Schema.FieldSchema(null, tupleSchema, DataType.BAG));
         catch (FrontendException e) 
            return new Schema(new Schema.FieldSchema(null, DataType.BAG));
        
    

    protected Schema.FieldSchema getMapValueSchema(Schema input) throws FrontendException 
        if (input == null || input.size() == 0) 
            return null;
        
        Schema.FieldSchema mapField = input.getField(0);
        if (mapField.type != DataType.MAP) 
            return null;
        

        Schema valueSchema = mapField.schema;
        if (valueSchema == null || valueSchema.size() == 0) 
            return null;
        
        Schema.FieldSchema valueField = valueSchema.getField(0);
        valueField.alias = "value";
        return valueField;
    

    @Override
    public List<FuncSpec> getArgToFuncMapping() throws FrontendException 
        List<FuncSpec> funcList = new ArrayList<FuncSpec>();
        funcList.add(new FuncSpec(this.getClass().getName(), new Schema(new Schema.FieldSchema(null, DataType.MAP))));
        return funcList;
    

    private static TupleFactory tupleFactory = TupleFactory.getInstance();
    private static BagFactory bagFactory = BagFactory.getInstance();

【讨论】:

【参考方案2】:

在您的代码中,catIds 只有两个字段 - elementIdcatId,并且您尝试在第二行访问 categoryIds。所以它不会工作。请修复它。

具体如何访问map值,需要将key用引号括起来,例如categoryIds#'catId'

【讨论】:

以上是关于PigLatin 映射键值的主要内容,如果未能解决你的问题,请参考以下文章

[677]. 键值映射

[677]. 键值映射

RestKit 对象映射:如何从键值映射到新对象/关系?

如何迭代无序映射特定键值?

map和multimap映射容器

《LeetCode之每日一题》:207.键值映射