2012-04-04 4 views
2

자바 UDF를 사용하여 가방에 튜플을 순위 지정하는 Java UDF를 작성하려고합니다. 튜플에는 순위에 대한 기준 인 값 열과 처음에 0으로 설정된 순위 열이 있습니다. 튜플은 값 열을 기준으로 정렬됩니다. 모든 튜플을 가방에 넣고 그 가방을 UDF로 전달되는 새로운 튜플 안에 넣습니다.아파치 돼지 Java UDF - 속성 값을 변경하지 않는 것 같습니다

UDF가 순위 열을 수정하지만 - 일단 메서드가 종료되면 값이 모두 다시 0이됩니다. 값을 "고정"하는 방법을 모르겠습니다.

도움이된다면 크게 감사하겠습니다.

여기 여기 내 자바 클래스

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 
import org.apache.pig.FilterFunc; 
import org.apache.pig.EvalFunc; 
import org.apache.pig.backend.executionengine.ExecException; 
import org.apache.pig.data.DataType; 
import org.apache.pig.data.Tuple; 
import org.apache.pig.data.DataBag; 
import org.apache.pig.impl.logicalLayer.FrontendException; 
import java.util.Iterator; 
import org.apache.pig.PigWarning; 

/** 
* 
* @author Winter 
*/ 
public class Ranker extends EvalFunc<String>{ 
    @Override 
    public String exec(Tuple tuple) throws IOException { 
     if (tuple == null || tuple.size() == 0) { 
      return null; 
     } 


     List<Object> list = tuple.getAll(); 
     DataBag db = (DataBag) list.get(0); 
     Integer num = (Integer)list.get(1); 

     Iterator<Tuple>itr = db.iterator(); 
     boolean containsNonNull = false; 
     int i = 1; 
     double previous=0; 
     while (itr.hasNext()) { 

      Tuple t= itr.next(); 
      double d = (Double)t.get(num.intValue()); 
      int rankCol = t.size()-1; 
      Integer rankVal = (Integer)t.get(rankCol); 
      if(i == 0){  
       System.out.println("i==0"); 
       previous = d; 
       t.set(rankCol, i); 
      } else { 
       if(d == previous) 
        t.set(rankCol, i); 
       else{ 
        System.out.print("d!==previous|" + d + "|"+ previous+"|"+rankVal); 
        t.set(rankCol, ++i); 
        rankVal = (Integer)t.get(rankCol); 
        System.out.println("|now rank val" + rankVal); 
        previous = d; 
       } 
      } 
     } 


     return "Y"; 
    } 
} 

이다 나는 돼지의 모든 호출 오전 방법입니다 -

REGISTER /myJar.jar; 
A = LOAD '/Users/Winter/milk-tea-coffee.tsv' as (year:chararray, milk:double); 
B = foreach A generate year, milk, 0 as rank; 
C = order B by milk asc; 
D = group C by rank order C by milk; 
E = foreach D generate D.C.year,D.C.milk,D.C.rank, piglet3.evalFunctions.Ranker(D.C,1); 
dump E; 

을 나는 그것 때문에 UDF 내부의 인쇄 문구의 UDF 내부에서 작업 말할 수있다 - d! == 이전 | 21.2 | 0.0 | 0 | 이제 val2를 계승하십시오! d! == 이전 | 21.6 | 21.2 | 0 | 이제 val3을 계승하십시오 d! == 이전 | 21.9 | 21.6 | 0 | 이제 val4를 계승하십시오 d ! == 이전 | 22.0 | 21.9 | 0 | 이제 val5를 계승하십시오 d! == 이전 | 22.5 | 22.0 | 0 | 이제 val6을 계승합니다. d! == 이전 22.9 | 22.5 | 0 이제 val7을 계승합니다. d! == 이전 23.0 22.9 0 0 이제 계급 val8 d ! == 이전 | 23.4 | 23.0 | 0 | 지금 val9 D 순위 == 이전 |! 23.8은 | 23.4 | 0 | 지금 val10 D 순위 == 이전 |! 23.9은 | 23.8이 | 0 | 현재 순위 val11

하지만 E 나 D 또는 C를 덤프 할 때 순위 열에는 0 만 포함됩니다.

답변

1

exec 함수는 사용자가 원하는 출력을 UDF에서 리턴해야합니다. 현재 exec 함수로 전달되는 튜플을 수정 한 다음 문자열 "Y"를 반환합니다. 즉, Pig가 UDF에서 출력 한 내용은 모두 "Y"입니다. 이 경우 "Y"대신 Tuple을 반환해야합니다.

나는 다음과 같은 코드가 의도에 가까운 생각,하지만 난 당신이 뭘 하려는지에 아주 명확하지 않다 :

import java.io.IOException; 
import java.util.ArrayList; 
import java.util.List; 
import org.apache.pig.FilterFunc; 
import org.apache.pig.EvalFunc; 
import org.apache.pig.backend.executionengine.ExecException; 
import org.apache.pig.data.DataType; 
import org.apache.pig.data.Tuple; 
import org.apache.pig.data.DataBag; 
import org.apache.pig.impl.logicalLayer.FrontendException; 
import java.util.Iterator; 
import org.apache.pig.PigWarning; 

/** 
* 
* @author Winter 
*/ 
public class Ranker extends EvalFunc<Tuple>{ 
    @Override 
    public Tuple exec(Tuple tuple) throws IOException { 
     if (tuple == null || tuple.size() == 0) { 
      return null; 
     } 


     List<Object> list = tuple.getAll(); 
     DataBag db = (DataBag) list.get(0); 
     Integer num = (Integer)list.get(1); 

     Iterator<Tuple>itr = db.iterator(); 
     boolean containsNonNull = false; 
     int i = 1; 
     double previous=0; 
     while (itr.hasNext()) { 

      Tuple t= itr.next(); 
      double d = (Double)t.get(num.intValue()); 
      int rankCol = t.size()-1; 
      Integer rankVal = (Integer)t.get(rankCol); 
      if(i == 0){  
       System.out.println("i==0"); 
       previous = d; 
       t.set(rankCol, i); 
      } else { 
       if(d == previous) 
        t.set(rankCol, i); 
       else{ 
        System.out.print("d!==previous|" + d + "|"+ previous+"|"+rankVal); 
        t.set(rankCol, ++i); 
        rankVal = (Integer)t.get(rankCol); 
        System.out.println("|now rank val" + rankVal); 
        previous = d; 
       } 
      } 
     } 


     return tuple; 
    } 
} 
+0

나는 내 문제의 부분은 그 튜플 당신의 순위를 생각 위의 튜플과 비교하여 전체 가방에서 작업해야합니다. – Winter

+0

예를 들어 튜플은 그 위의 1 위 터플을 볼 수있는 경우를 제외하고는 2 위에 있는지 알 수 없습니다. 그래서 내가 모든 튜플을 가방에 넣은 다음 그 가방을 새로운 튜플에 넣는 이유가 있습니다. 그러나 전체적으로 더 좋은 방법이있을 수 있습니다. – Winter

+0

당신은 정확했습니다! 정말 고마워! – Winter

관련 문제