Как я могу включить текущее имя входного файла в мой скрипт Pig Latin?
Я обрабатываю данные из набора файлов, которые содержат штамп даты как часть имени файла. Данные в файле не содержат отметку даты. Я хотел бы обработать имя файла и добавить его к одной из структур данных в сценарии. Есть ли способ сделать это в 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. Похоже, это должно было произойти, поскольку после загрузки данных уже слишком поздно возвращаться к исходному имени файла.
4 ответа
Вы можете использовать PigStorage, указав -tagsource следующим образом
A = LOAD 'input' using PigStorage(',','-tagsource');
B = foreach A generate INPUT_FILE_NAME;
Первое поле в каждом кортеже будет содержать входной путь (INPUT_FILE_NAME)
В соответствии с документом API http://pig.apache.org/docs/r0.10.0/api/org/apache/pig/builtin/PigStorage.html
Дэн
Pig wiki как пример PigStorageWithInputPath, у которого было имя файла в дополнительном поле chararray:
пример
A = load '/directory/of/files/*' using PigStorageWithInputPath()
as (field1:chararray, field2:int, field3:chararray);
UDF
// 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;
}
}
-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
Способ сделать это в 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'
Посмотрите на замечательные слайды Жюльена Ле Дема, если вам интересно. Там также тонна документации на http://pig.apache.org/docs/r0.9.2/cont.pdf.