我正在尝试为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.
由于我没有找到任何提及这种转变的文件,我希望你能为我提供一些建议!
答案 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的源代码作为指导。