2012-06-08 176 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(); 
}