2013-08-26 3 views
3

У меня есть медленно изменяющиеся метаданные, которые хранятся в режиме реального времени на HDFS. Я хотел бы написать задание на свиньи, которое конденсирует эти строки до самой последней строки для каждого ключа.Получить последнюю строку по метке в свине

Например, для этих данных (заголовки столбцов добавлены для ясности):

ts meta key 
-- ---- --- 
1 foo id1 
2 que id2 
3 que id2 
4 foo id1 
5 pasa id2 
6 pasa id2 
7 foo id1 
8 pasa id2 
9 pasa id2 
10 pasa id2 
11 pasa id2 
12 hombre id2 
13 foo id1 
14 foo id1 
15 hombre id2 
16 bar id1 
17 bar id1 
18 bar id1 
19 bar id1 
20 bar id1 

Я хотел бы ожидать, чтобы получить выход:

15 hombre id2 
20 bar id1 

Я только начинаю изучать входы и выходы из Pig Latin - есть ли встроенный способ сделать это у свиньи или какой-нибудь библиотеки уже, или я должен смотреть на запись UDF?

ответ

6

Это хорошее место для вложенного Еогеасп:

A = LOAD '$input' AS (ts:int, meta:chararray, key:chararray); 
B = 
    FOREACH (GROUP A BY key) { 
     byts = ORDER A BY ts DESC; 
     newest = LIMIT byts 1; 
     GENERATE FLATTEN(newest); 
    }; 

Тестирование на ваших данных (я преобразовал его быть с разделителями табуляции):

(20,bar,id1) 
(15,hombre,id2) 

С помощью этого метода вы гарантировано всего одна строка для каждого ключа, даже если у вас две строки с самой последней отметкой времени (хотя это может не иметь значения для ваших данных).

+0

Спасибо, это сработало хорошо. Я немного обеспокоен тем, что сортировка не будет масштабироваться так же хорошо, как решение из @ mr2ert, но в итоге получается единственная строка результата, поэтому я буду ждать, пока проблемы с производительностью не возникнут, прежде чем пытаться оптимизировать. –

1

Одним из способов вы можете сделать это:

A = LOAD 'myinput' USING PigStorage(' ') 
    AS (ts:int, meta:chararray, key:chararray) ; 

-- Group by key, then find the newest ts for each key 
B = FOREACH (GROUP A BY key) 
    GENERATE MAX(A.ts) AS newest, 
      FLATTEN(A) ; 

-- Now that each line has the newest (appropriate) ts, 
-- we can use it to filter the input 
C = FILTER B BY newest == ts ; 

Выход:

(20,20,bar,id1) 
(15,15,hombre,id2) 

Обратите внимание, что если вы не хотите иметь дубликат ts, вы можете проецировать его сейчас нравится:

C = FOREACH (FILTER B BY newest == ts) 
    GENERATE A::ts AS ts, A::meta AS meta, A::key AS key ; 

Но было бы лучше просто оставить дополнительные ts один прямо сейчас и проецировать его как часть более позднего FOREACH, чтобы ограничить количество заданий.

Обновление: Этот метод вернет все линии с наибольшим ts для каждого ключа. Например, если данные, как это:

(11,nope,id1) 
(20,foo,id1) 
(20,bar,id1) 

Затем он вернется как foo и bar.

+0

Это тоже неплохое решение - я выбрал один из @WinnieNicklaus, так как он заканчивается одной строкой на ключ, хотя я действительно не ожидаю столкновения с меткой времени, так что любой из них, вероятно, будет работать нормально. –

Смежные вопросы