Как я могу включить текущее имя входного файла в мою Pig Latin script?
Я обрабатываю данные из набора файлов, которые содержат отметку даты в качестве части имени файла. Данные в файле не содержат штамп даты. Я хотел бы обработать имя файла и добавить его в одну из структур данных в script. Есть ли способ сделать это в Pig Latin (возможно, расширение PigStorage?) Или мне нужно предварительно обработать все файлы с помощью Perl и т.д. Заранее?
Я представляю себе что-то вроде следующего:
-- Load two fields from file, then generate a third from the filename
rawdata = LOAD '/directory/of/files/' USING PigStorage AS (field1:chararray, field2:int, field3:filename);
-- Reformat the filename into a datestamp
annotated = FOREACH rawdata GENERATE
REGEX_EXTRACT(field3,'*-(20\d{6})-*',1) AS datestamp,
field1, field2;
Обратите внимание на специальный тип данных "filename" в инструкции LOAD. Похоже, что это должно было случиться там, как только данные были загружены слишком поздно, чтобы вернуться к исходному имени файла.
Ответы
Ответ 1
Вы можете использовать PigStorage, указав -tagsource следующим образом
A = LOAD 'input' using PigStorage(',','-tagsource');
B = foreach A generate INPUT_FILE_NAME;
Первое поле в каждом Tuple будет содержать входной путь (INPUT_FILE_NAME)
В соответствии с API doc http://pig.apache.org/docs/r0.10.0/api/org/apache/pig/builtin/PigStorage.html
Dan
Ответ 2
Вики-свиньи в качестве примера PigStorageWithInputPath, который имел имя файла в дополнительном поле chararray:
Пример
A = load '/directory/of/files/*' using PigStorageWithInputPath()
as (field1:chararray, field2:int, field3:chararray);
ОДС
// Note that there are several versions of Path and FileSplit. These are intended:
import org.apache.hadoop.fs.Path;
import org.apache.hadoop.mapreduce.RecordReader;
import org.apache.hadoop.mapreduce.lib.input.FileSplit;
import org.apache.pig.backend.hadoop.executionengine.mapReduceLayer.PigSplit;
import org.apache.pig.builtin.PigStorage;
import org.apache.pig.data.Tuple;
public class PigStorageWithInputPath extends PigStorage {
Path path = null;
@Override
public void prepareToRead(RecordReader reader, PigSplit split) {
super.prepareToRead(reader, split);
path = ((FileSplit)split.getWrappedSplit()).getPath();
}
@Override
public Tuple getNext() throws IOException {
Tuple myTuple = super.getNext();
if (myTuple != null)
myTuple.append(path.toString());
return myTuple;
}
}
Ответ 3
-tagSource устарел в Pig 0.12.0.
Вместо этого используйте
-tagFile - добавляет имя исходного файла источника в начало каждого кортежа.
-tagPath - добавляет путь к исходному файлу исходного кода в начало каждого кортежа.
A = LOAD '/user/myFile.TXT' using PigStorage(',','-tagPath');
DUMP A ;
предоставит вам полный путь к файлу в качестве первого столбца
( hdfs://myserver/user/blo/input/2015.TXT,439,43,05,4,NAVI,PO,P&C,P&CR,UC,40)
Отказ: http://pig.apache.org/docs/r0.12.0/api/org/apache/pig/builtin/PigStorage.html
Ответ 4
Способ сделать это в Bash и PigLatin можно найти по адресу: Как загрузить каждый файл в папке с помощью PIG?.
То, что я делал в последнее время, и считаю, что это намного чище, это вложение Pig в Python. Это позволяет вам бросать всевозможные переменные и такие между ними. Простой пример:
#!/path/to/jython.jar
# explicitly import Pig class
from org.apache.pig.scripting import Pig
# COMPILE: compile method returns a Pig object that represents the pipeline
P = Pig.compile(
"a = load '$in'; store a into '$out';")
input = '/path/to/some/file.txt'
output = '/path/to/some/output/on/hdfs'
# BIND and RUN
results = P.bind({'in':input, 'out':output}).runSingle()
if results.isSuccessful() :
print 'Pig job succeeded'
else :
raise 'Pig job failed'
Взгляните на Julien Le Dem great slides как введение в это, если вам интересно. Там также тонна документации на http://pig.apache.org/docs/r0.9.2/cont.pdf.