2013-08-12 49 views
2

讓我來解釋一下這個問題。我有這行代碼:豬 - 如何迭代一袋地圖

u = FOREACH persons GENERATE FLATTEN($0#'experiences') as j; 
dump u; 

產生以下輸出:

([id#1,date_begin#12 2012,description#blabla,date_end#04 2013],[id#2,date_begin#02 2011,description#blabla2,date_end#04 2013]) 
([id#1,date_begin#12 2011,description#blabla3,date_end#04 2012],[id#2,date_begin#02 2010,description#blabla4,date_end#04 2011]) 

然後,當我這樣做:

p = foreach u generate j#'id', j#'description'; 
dump p; 

我有這樣的輸出:

(1,blabla) 
(1,blabla3) 

但這不是我想要的。我想有這樣的輸出:

(1,blabla) 
(2,blabla2) 
(1,blabla3) 
(2,blabla4) 

我怎麼能有這個?

非常感謝。

+0

在你做'轉儲j中的第一塊;',你的意思是'傾U;'?另外,你能提供'DESCRIBE u'的輸出嗎? – mr2ert

+0

是的,這是傾銷ü謝謝。 DESCRIBE u產生這樣的輸出:u:{j:bytearray} –

回答

3

我假設$ 0你是FLATTEN ing u是一個元組。

總體問題是j只引用元組中的第一個映射。爲了得到你想要的輸出,你必須將每個元組轉換成一個包,然後FLATTEN它。

如果你知道,每個元組最多有兩個地圖,你可以這樣做:

-- My B is your u 
B = FOREACH A GENERATE (tuple(map[],map[]))$0#'experiences' AS T ; 
B2 = FOREACH B GENERATE FLATTEN(TOBAG(T.$0, T.$1)) AS j ; 

C = foreach B2 generate j#'id', j#'description' ; 

如果你不知道有多少個字段將在元組,那麼這將是更難。


注:這適用於豬0.10。

對於地圖的不確定數量的元組,我能想到的最好的答案是使用UDF來解析字節組:

myudf.py

@outputSchema('vals: {(val:map[])}') 
def foo(the_input): 
    # This converts the indeterminate number of maps into a bag. 
    foo = [chr(i) for i in the_input] 
    foo = ''.join(foo).strip('()') 
    out = [] 
    for f in foo.split('],['): 
     f = f.strip('[]') 
     out.append(dict((k, v) for k, v in [ i.split('#') for i in f.split(',')])) 
    return out 

myscript.pig

register 'myudf.py' using jython as myudf ; 
B = FOREACH A GENERATE FLATTEN($0#'experiences') ; 

T1 = FOREACH B GENERATE FLATTEN(myudf.foo($0)) AS M ; 
T2 = FOREACH T1 GENERATE M#'id', M#'description' ; 

然而,這依賴於一個事實,即#,],[將不會出現在地圖中的任何鍵或值中。


注:這適用於豬0.11。

因此,似乎豬在這種情況下如何處理python UDF的輸入。字節陣列不是輸入到foo的字節陣列,而是自動轉換爲適當的類型。在這種情況下,它使一切變得更容易:

myudf。PY

@outputSchema('vals: {(val:map[])}') 
def foo(the_input): 
    # This converts the indeterminate number of maps into a bag. 
    out = [] 
    for map in the_input: 
     out.append(map) 
    return out 

myscript.pig

register 'myudf.py' using jython as myudf ; 

# This time you should pass in the entire tuple. 
B = FOREACH A GENERATE $0#'experiences' ; 

T1 = FOREACH B GENERATE FLATTEN(myudf.foo($0)) AS M ; 
T2 = FOREACH T1 GENERATE M#'id', M#'description' ; 
+0

不幸的是,我不知道元組中有多少個字段:( –

+0

@shanks_roux我已經更新了我的答案,以包含未知數量的字段。 – mr2ert

+0

感謝您的幫助!但爲什麼你不滿意你的解決方案? –