2012-03-17 8 views
13

Estoy procesando datos de un conjunto de archivos que contienen un sello de fecha como parte del nombre de archivo. Los datos dentro del archivo no contienen el sello de fecha. Me gustaría procesar el nombre del archivo y agregarlo a una de las estructuras de datos dentro del script. ¿Hay alguna manera de hacerlo dentro de Pig Latin (una extensión de PigStorage, tal vez?) O ¿necesito preprocesar todos los archivos usando Perl o similares de antemano?¿Cómo puedo incorporar el nombre de archivo actual en mi script de Pig Latin?

Me imagino algo como lo siguiente:

-- 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; 

Nota el "nombre de archivo" especial tipo de datos en la declaración de carga. Parece que tendría que ocurrir allí, ya que una vez que los datos se han cargado, es demasiado tarde para volver al nombre del archivo de origen.

Respuesta

13

El wiki Pig como un ejemplo de PigStorageWithInputPath que tenía el nombre de archivo en un campo chararray adicional:

Ejemplo

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; 
    } 
} 
1

Una manera de hacer esto en Bash y PigLatin se puede encontrar en: How Can I Load Every File In a Folder Using PIG?.

Lo que he estado haciendo últimamente, sin embargo, y para ser mucho más limpio está incrustando Pig en Python. Eso te permite lanzar todo tipo de variables y tal entre los dos. Un ejemplo sencillo es:

#!/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' 

Tenga una mirada en Julien Le Dem's great slides como una introducción a esto, si usted está interesado. También hay un montón de documentación en http://pig.apache.org/docs/r0.9.2/cont.pdf.

3

-tagSource está en desuso en Pig 0.12.0. En su lugar use

-tagFile - Añade el nombre del archivo de origen de entrada al comienzo de cada tupla.
-tagPath: agrega la ruta del archivo de origen de entrada al comienzo de cada tupla.

A = LOAD '/user/myFile.TXT' using PigStorage(',','-tagPath'); 
DUMP A ; 

le dará la ruta del archivo completo como primera columna

(hdfs://myserver/user/blo/input/2015.TXT,439,43,05,4,NAVI,PO,P&C,P&CR,UC,40) 

Refrence: http://pig.apache.org/docs/r0.12.0/api/org/apache/pig/builtin/PigStorage.html

Cuestiones relacionadas