[HADOOP] GenericUDF 기능은 구조체의 배열에서 필드를 추출하는
HADOOPGenericUDF 기능은 구조체의 배열에서 필드를 추출하는
나는 각 레코드 배열 내의 특정 구조체 필드 (들)을 모두 수집하고,뿐만 아니라 배열을 반환하는 GenericUDF 함수를 작성하려합니다.
나는 GenericUDF를 (아래) 쓰고, 작동하지만 것 같다 :
1) 내가 외부 테이블에서이 작업을 수행하고 때 작동하지 않습니다, 그것은, 관리 테이블에 어떤 생각을 잘 작동?
2) 나는이에 대한 테스트를 작성하는 힘든 시간을 보내고 있어요. 나는 지금까지이 테스트를 첨부, 그것은 작동하지 않습니다, 항상 '인 java.util.ArrayList가 org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector 캐스트 할 수없는'또는 'LazyString에 문자열을 캐스팅 할 수없는지고, 나는 evalue 방법에 대한 구조체의 목록을 제공 어떻게 내 질문은?
어떤 도움은 매우 극명하게 될 것이다.
탁자:
CREATE EXTERNAL TABLE FOO (
TS string,
customerId string,
products array< struct<productCategory:string> >
)
PARTITIONED BY (ds string)
ROW FORMAT SERDE 'some.serde'
WITH SERDEPROPERTIES ('error.ignore'='true')
LOCATION 'some_locations'
;
기록의 행을 원하는 분야 1340321132000 'some_company'[{ "productCategory": "신발"}, { "productCategory": "안경"}]
이건 내 코드입니다 :
import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.lazy.LazyString;
import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector.Category;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.PrimitiveObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.StructField;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector;
import org.apache.hadoop.io.Text;
import java.util.ArrayList;
@Description(name = "extract_product_category",
value = "_FUNC_( array< struct<productcategory:string> > ) - Collect all product category field values inside an array of struct(s), and return the results in an array<string>",
extended = "Example:\n SELECT _FUNC_(array_of_structs_with_product_category_field)")
public class GenericUDFExtractProductCategory
extends GenericUDF
{
private ArrayList ret;
private ListObjectInspector listOI;
private StructObjectInspector structOI;
private ObjectInspector prodCatOI;
@Override
public ObjectInspector initialize(ObjectInspector[] args)
throws UDFArgumentException
{
if (args.length != 1) {
throw new UDFArgumentLengthException("The function extract_product_category() requires exactly one argument.");
}
if (args[0].getCategory() != Category.LIST) {
throw new UDFArgumentTypeException(0, "Type array<struct> is expected to be the argument for extract_product_category but " + args[0].getTypeName() + " is found instead");
}
listOI = ((ListObjectInspector) args[0]);
structOI = ((StructObjectInspector) listOI.getListElementObjectInspector());
if (structOI.getAllStructFieldRefs().size() != 1) {
throw new UDFArgumentTypeException(0, "Incorrect number of fields in the struct, should be one");
}
StructField productCategoryField = structOI.getStructFieldRef("productCategory");
//If not, throw exception
if (productCategoryField == null) {
throw new UDFArgumentTypeException(0, "NO \"productCategory\" field in input structure");
}
//Are they of the correct types?
//We store these object inspectors for use in the evaluate() method
prodCatOI = productCategoryField.getFieldObjectInspector();
//First are they primitives
if (prodCatOI.getCategory() != Category.PRIMITIVE) {
throw new UDFArgumentTypeException(0, "productCategory field must be of string type");
}
//Are they of the correct primitives?
if (((PrimitiveObjectInspector)prodCatOI).getPrimitiveCategory() != PrimitiveObjectInspector.PrimitiveCategory.STRING) {
throw new UDFArgumentTypeException(0, "productCategory field must be of string type");
}
ret = new ArrayList();
return ObjectInspectorFactory.getStandardListObjectInspector(PrimitiveObjectInspectorFactory.writableStringObjectInspector);
}
@Override
public ArrayList evaluate(DeferredObject[] arguments)
throws HiveException
{
ret.clear();
if (arguments.length != 1) {
return null;
}
if (arguments[0].get() == null) {
return null;
}
int numElements = listOI.getListLength(arguments[0].get());
for (int i = 0; i < numElements; i++) {
LazyString prodCatDataObject = (LazyString) (structOI.getStructFieldData(listOI.getListElement(arguments[0].get(), i), structOI.getStructFieldRef("productCategory")));
Text productCategoryValue = ((StringObjectInspector) prodCatOI).getPrimitiveWritableObject(prodCatDataObject);
ret.add(productCategoryValue);
}
return ret;
}
@Override
public String getDisplayString(String[] strings)
{
assert (strings.length > 0);
StringBuilder sb = new StringBuilder();
sb.append("extract_product_category(");
sb.append(strings[0]);
sb.append(")");
return sb.toString();
}
}
내 테스트 :
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredObject;
import org.apache.hadoop.hive.serde2.objectinspector.ListObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorFactory;
import org.apache.hadoop.hive.serde2.objectinspector.StructObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;
import org.testng.annotations.Test;
import java.util.ArrayList;
import java.util.List;
public class TestGenericUDFExtractShas
{
ArrayList<String> fieldNames = new ArrayList<String>();
ArrayList<ObjectInspector> fieldObjectInspectors = new ArrayList<ObjectInspector>();
@Test
public void simpleTest()
throws Exception
{
ListObjectInspector firstInspector = new MyListObjectInspector();
ArrayList test = new ArrayList();
test.add("test");
ArrayList test2 = new ArrayList();
test2.add(test);
StructObjectInspector soi = ObjectInspectorFactory.getStandardStructObjectInspector(test, test2);
fieldNames.add("productCategory");
fieldObjectInspectors.add(PrimitiveObjectInspectorFactory.writableStringObjectInspector);
GenericUDF.DeferredObject firstDeferredObject = new MyDeferredObject(test2);
GenericUDF extract_product_category = new GenericUDFExtractProductCategory();
extract_product_category.initialize(new ObjectInspector[]{firstInspector});
extract_product_category.evaluate(new DeferredObject[]{firstDeferredObject});
}
public class MyDeferredObject implements DeferredObject
{
private Object value;
public MyDeferredObject(Object value) {
this.value = value;
}
@Override
public Object get() throws HiveException
{
return value;
}
}
private class MyListObjectInspector implements ListObjectInspector
{
@Override
public ObjectInspector getListElementObjectInspector()
{
return ObjectInspectorFactory.getStandardStructObjectInspector(fieldNames, fieldObjectInspectors);
}
@Override
public Object getListElement(Object data, int index)
{
List myList = (List) data;
if (myList == null || index > myList.size()) {
return null;
}
return myList.get(index);
}
@Override
public int getListLength(Object data)
{
if (data == null) {
return -1;
}
return ((List) data).size();
}
@Override
public List<?> getList(Object data)
{
return (List) data;
}
@Override
public String getTypeName()
{
return null; //To change body of implemented methods use File | Settings | File Templates.
}
@Override
public Category getCategory()
{
return Category.LIST;
}
}
}
해결법
-
==============================
1.나는 시험에 말할 수 있지만,주의해야 할 점은 아래에 설명과 함께, 나는 외부 테이블의 문제에 대한 해결책을 가지고 생각합니다.
나는 시험에 말할 수 있지만,주의해야 할 점은 아래에 설명과 함께, 나는 외부 테이블의 문제에 대한 해결책을 가지고 생각합니다.
내 요구에 코드를 적응에서 나는 평가 방법에 긴에 문자열을 변경 :
코드 :
LazyString prodCatDataObject = (LazyString) (structOI.getStructFieldData(listOI.getListElement(arguments[0].get(), i), structOI.getStructFieldRef("productCategory"))); Text productCategoryValue = ((StringObjectInspector) prodCatOI).getPrimitiveWritableObject(prodCatDataObject);
내 예전의 코드 :
LazyLong indDataObject = (LazyLong) (structOI.getStructFieldData(listOI.getListElement(arguments[0].get(), i), structOI.getStructFieldRef(indexName))); LongWritable indValue = ((LazyLongObjectInspector) indOI).getPrimitiveWritableObject(indDataObject);
당신은 그들이 등 다른 데이터 유형과 같은 논리입니다 볼 수 있습니다
이 비 외부 테이블과 날 위해 일했습니다. 외부 테이블에서 작동하지 않았다.
나는이 내 예전의 코드를 대체하여이 문제를 해결할 수 있었다 :
long indValue = (Long) (structOI.getStructFieldData(listOI.getListElement(arguments[0].get(), i), structOI.getStructFieldRef(indexName)));
다른 버전에서는, 나는 텍스트를 반환 한 경우
당신은 아마, 즉 첫 번째 단계에서 텍스트 / 문자열로 변환하여, 비슷한 일을 할 수 있습니다.
당신은 또한 (DeferredObject [] 인수를) 평가 공공 오브젝트 공공 텍스트 평가 (DeferredObject [] 인수)을 변경해야 할 수도 있습니다.
배열은 여기에서 확인할 수 있습니다 처리 할 몇 가지 작업 UDF의 소스 코드.
이제주의에 대해 :이 ORC로 저장 테이블에 대해 작업 표시되지 않습니다. (어느 쪽도 원래의 코드가하는 당신을 신경 쓰지). 나는 아마 이것에 대해 질문을 만듭니다. 나는 문제가 무엇인지 모르겠습니다.
from https://stackoverflow.com/questions/15694555/a-genericudf-function-to-extract-a-field-from-an-array-of-structs by cc-by-sa and MIT license
'HADOOP' 카테고리의 다른 글
[HADOOP] ORC의 오류 때 java.io.IOException로 Sqoop을 가져 오기 : HCat 상태 1로 종료 (0) | 2019.09.22 |
---|---|
[HADOOP] 감소 하둡지도를위한 파이썬에서 사용자 정의 쓰기 가능한 키 / 값 유형을 작성? (0) | 2019.09.22 |
[HADOOP] 작업은 예 하둡 0.23.0에서 실행 매달려 때 (0) | 2019.09.22 |
[HADOOP] 오류 KeyProviderCache : 키와 URI를 찾을 수 없습니다 (0) | 2019.09.22 |
[HADOOP] Hadoop-> Mapper-> 우리가 어떻게 주어진 입력 경로에서 각 파일에서만 상위 N 행을 읽을 수 있습니까? (0) | 2019.09.22 |