2013-12-19 3 views
3

У меня есть сценарий, который загрузить некоторые данные о местах:Pig - прохождение Databag в UDF конструктор

venues = LOAD 'venues_extended_2.csv' USING org.apache.pig.piggybank.storage.CSVLoader() AS (Name:chararray, Type:chararray, Latitude:double, Longitude:double, City:chararray, Country:chararray); 

Тогда я хочу, чтобы создать UDF, который имеет конструктор, который принимает тип заведения.

Так что я попытался определить это UDF так:

DEFINE GenerateVenues org.gla.anton.udf.main.GenerateVenues(venues); 

А вот фактическая UDF:

public class GenerateVenues extends EvalFunc<Tuple> { 

    TupleFactory mTupleFactory = TupleFactory.getInstance(); 
    BagFactory mBagFactory = BagFactory.getInstance(); 

    private static final String ALLCHARS = "(.*)"; 
    private ArrayList<String> venues; 

    private String regex; 

    public GenerateVenues(DataBag venuesBag) { 
     Iterator<Tuple> it = venuesBag.iterator(); 
     venues = new ArrayList<String>((int) (venuesBag.size() + 1)); // possible fails!!! 
     String current = ""; 
     regex = ""; 
     while (it.hasNext()){ 
      Tuple t = it.next(); 
      try { 
       current = "(" + ALLCHARS + t.get(0) + ALLCHARS + ")"; 
       venues.add((String) t.get(0)); 
      } catch (ExecException e) { 
       throw new IllegalArgumentException("VenuesRegex: requires tuple with at least one value"); 
      } 
      regex += current + (it.hasNext() ? "|" : ""); 
     } 
    } 

    @Override 
    public Tuple exec(Tuple tuple) throws IOException { 
     // expect one string 
     if (tuple == null || tuple.size() != 2) { 
      throw new IllegalArgumentException(
        "BagTupleExampleUDF: requires two input parameters."); 
     } 
     try { 
      String tweet = (String) tuple.get(0); 
      for (String venue: venues) 
      { 
       if (tweet.matches(ALLCHARS + venue + ALLCHARS)) 
       { 
        Tuple output = mTupleFactory.newTuple(Collections.singletonList(venue)); 
        return output; 
       } 
      } 
      return null; 
     } catch (Exception e) { 
      throw new IOException(
        "BagTupleExampleUDF: caught exception processing input.", e); 
     } 
    } 
} 

При выполнении сценария увольняет ошибки в DEFINE части непосредственно перед (venues);:

2013-12-19 04:28:06,072 [main] ERROR org.apache.pig.tools.grunt.Grunt - ERROR 1200: <file script.pig, line 6, column 60> mismatched input 'venues' expecting RIGHT_PAREN 

Очевидно, что я делаю что-то не так, Выясните, что случилось. Это UDF, который не может принять отношение площадок в качестве параметра. Или отношение не представлено DataBag вот так public GenerateVenues(DataBag venuesBag)? Спасибо!

PS Я использую версию для свиней 0.11.1.1.3.0.0-107.

ответ

0

Вы не можете использовать отношение в качестве параметра в конструкторе UDF. В качестве аргументов могут передаваться только строки, и если они действительно имеют другой тип, вам придется разбирать их в конструкторе.

4

Как уже сказал @WinnieNicklaus, вы можете только передать строки конструкторам UDF.

Сказав это, решение проблемы связано с распределенным кешем, вам необходимо переопределить public List<String> getCacheFiles(), чтобы вернуть список имен файлов, которые будут доступны через распределенный кеш. При этом вы можете прочитать файл как локальный файл и создать свою таблицу.

Недостатком является то, что свиньи не имеет функции инициализации, так что вы должны сделать что-то вроде

private void init() { 
    if (!this.initialized) { 
     // read table 
    } 
} 

, а затем назвать это как первая вещь из exec.

Смежные вопросы