Hive UDF文本到数组

时间:2013-06-16 20:05:20

标签: hadoop hive user-defined-functions

我正在尝试为Hive创建一些UDF,这比我已经提供的split()函数提供了更多功能。

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;
  }
}

这在Hive中有效。我将这个类导出到一个jar文件中。然后我用

将它加载到Hive中

add jar /path/to/myJar.jar;

并使用

创建一个函数

create temporary function lower_case as 'LowerCase';

我有一个带有String字段的表。声明是:

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.

由于我没有找到任何提及这种转变的文件,我希望你能为我提供一些建议!

2 个答案:

答案 0 :(得分:10)

实际上'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;
  }
}

答案 1 :(得分:2)

我不认为'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