2012-06-08 178 views
1

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

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

这是我收到的错误:在分析过程中错误: ERROR 1000。遇到““CATID ”“ 在第28行,列64 期待之一: ”空“ ...... ... ...... ”空“ ......

是什么我试图不可能?每次使用地图时,是否需要明确说明键值(例如:categoryIds#'51')?

回答

0

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

具体为如何访问映射值,则需要用引号括起来的关键,e.g categoryIds#'catId'

2

据我所知,猪不提供任何内置的方式来获得地图密钥。对于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(); 
}