2013-06-16 5 views
1

Я пытаюсь создать некоторый UDF для Hive, который дает мне больше функциональности, чем уже предоставленная функция split().Hive UDF Текст массиву

import org.apache.hadoop.hive.ql.exec.UDF; 
import org.apache.hadoop.io.Text; 

public class LowerCase extends UDF { 

    public Text evaluate(final Text text) { 
    return new Text(stemWord(text.toString())); 
    } 

    /** 
    * Stems words to normal form. 
    * 
    * @param word 
    * @return Stemmed word. 
    */ 
    private String stemWord(String word) { 
    word = word.toLowerCase(); 
    // Remove special characters 
    // Porter stemmer 
    // ... 
    return word; 
    } 
} 

Это работает в улье. Я экспортирую этот класс в файл jar. Тогда я загрузить его в улей с

add jar /path/to/myJar.jar;

и создать функцию с помощью

create temporary function lower_case as 'LowerCase';

У меня есть таблица с полем Струнный в нем. Заявление тогда:

select lower_case(text) from documents;

Но теперь я хочу, чтобы создать функцию, возвращающую массив (как, например, разделение делает).

import java.util.ArrayList; 
import java.util.List; 
import java.util.StringTokenizer; 

import org.apache.hadoop.hive.ql.exec.UDF; 
import org.apache.hadoop.io.Text; 

public class WordSplit extends UDF { 

    public Text[] evaluate(final Text text) { 
    List<Text> splitList = new ArrayList<>(); 

    StringTokenizer tokenizer = new StringTokenizer(text.toString()); 

    while (tokenizer.hasMoreElements()) { 
     Text word = new Text(stemWord((String) tokenizer.nextElement())); 

     splitList.add(word); 
    } 

    return splitList.toArray(new Text[splitList.size()]); 
    } 

    /** 
    * Stems words to normal form. 
    * 
    * @param word 
    * @return Stemmed word. 
    */ 
    private String stemWord(String word) { 
    word = word.toLowerCase(); 
    // Remove special characters 
    // Porter stemmer 
    // ... 
    return word; 
    } 
} 

К сожалению, эта функция не работает, если я выполняю ту же самую процедуру загрузки, о которой говорилось выше. Я получаю следующее сообщение об ошибке:

FAILED: SemanticException java.lang.IllegalArgumentException: Error: name expected at the position 7 of 'struct<>' but '>' is found.

Как я не нашел никаких документов упоминания такого рода трансформации, я надеюсь, что вы будете иметь некоторые советы для меня!

ответ

1

Я не думаю, что интерфейс UDF обеспечит то, что вы хотите. Вы хотите использовать GenericUDF. Я использовал бы источник раскола UDF в качестве руководства.

http://grepcode.com/file/repository.cloudera.com/content/repositories/releases/org.apache.hadoop.hive/hive-exec/0.7.1-cdh3u1/org/apache/hadoop/hive/ql/udf/generic/GenericUDFSplit.java

+1

Спасибо, с 'GenericUDF' интерфейс он работал отлично! – fyaa

+0

Вы отвечаете несколько вводящим в заблуждение. Собственно, интерфейс UUF от Hive может достичь этого. См. Ответ @swdev. – zeekvfu

9

На самом деле интерфейс 'UDF' делает поддержку возвращения массива.

Возвращение ArrayList<Text> или даже ArrayList<String> вместо Text[]

Ваш код должен выглядеть следующим образом:

import java.util.ArrayList; 
import java.util.List; 
import java.util.StringTokenizer; 

import org.apache.hadoop.hive.ql.exec.UDF; 
import org.apache.hadoop.io.Text; 

public class WordSplit extends UDF { 

    public ArrayList<String> evaluate(final Text text) { 
    ArrayList<String> splitList = new ArrayList<String>(); 

    StringTokenizer tokenizer = new StringTokenizer(text.toString()); 

    while (tokenizer.hasMoreElements()) { 
     String word = stemWord((String) tokenizer.nextElement()); 
     splitList.add(word); 
    } 
    return splitList; 
    } 

    /** 
    * Stems words to normal form. 
    * 
    * @param word 
    * @return Stemmed word. 
    */ 
    private String stemWord(String word) { 
    word = word.toLowerCase(); 
    return word; 
    } 
} 
Смежные вопросы