Lectura de campos NULLABLE con BigQueryIO en Apache Beam

Foto de Ben Hershey en Unsplash

Al leer datos de BigQuery usando BigQueryIO en una canalización de Apache Beam escrita en Java, puede leer los registros como TableRow (conveniente pero que ofrece menos rendimiento) o como GenericRecord (rendimiento adicional, pero también puede requerirse un trabajo adicional en su código).

En una publicación anterior , mostré que cuando se usa GenericRecord, los tipos BigQuery se asignan más o menos fácilmente a los tipos Java, con la excepción de NUMERIC, que requiere un trabajo adicional.

Pero en realidad eso es solo para las columnas BigQuery que se requieren . Las columnas anulables necesitan un análisis adicional para extraer los valores de los registros.

Al crear el esquema para una tabla en BigQuery, podemos tener tres modos diferentes para las columnas : anulables , obligatorios y repetidos .

El modo predeterminado es anulable . Un campo anulable puede contener un valor del tipo de columna o, bueno, nulo. Fácil.

Sin embargo, al leer los datos en BigQueryIO como GenericRecord , los esquemas Avro no tienen tipos anulables. Tienen un tipo nulo , además de otros tipos. Entonces, para especificar que un campo puede contener valores nulos, debe especificar varios tipos para el mismo campo en Avro. Eso en realidad se llama unión . Por ejemplo, si su campo de nombre myfield que contiene cadenas y es anulable, el esquema Avro sería como este:

 {"name": "myfield", "type": ["null", "string"]} 

En un GenericRecord , el tipo de myfield sería union , y tendríamos que atravesar los tipos y valores de ese campo, para recuperar realmente el valor de myfield (ya sea un NULL o una cadena).

Así que supongamos que tenemos las siguientes dos variables (todos los fragmentos de código están en Java):

 String fieldName; // el nombre de la columna 
GenericRecord rec; // los valores en la fila a analizar

Podemos recuperar el esquema y el tipo de ese campo

 Esquema fieldSchema = rec.getSchema (). GetField (fieldName) .schema (); 
Schema.Type type = fieldSchema.getType ();

Y ahora, es cuando debemos verificar si el tipo es UNION

 if (type == Schema.Type.UNION) { 
// Tenemos un campo NULLABLE
...

También podríamos haber comprobado si la longitud de fieldSchema.getTypes () es 1 o 2. Será 1 para los campos obligatorios y 2 para los campos anulables.

Después de verificar que tenemos un campo NULLABLE, podemos recuperar los tipos, intentar identificar el tipo NULL (entre los dos tipos contenidos en el campo) y usar el otro tipo para analizar el valor:

 Lista  tipos = fieldSchema.getTypes (); 
// Veamos cuál es el NULL y quédate con el otro
if (types.get (0) .getType () == Schema.Type.NULL) {
type = types.get (1) .getType ();
} más {
type = types.get (0) .getType ();
}

Y después de eso, podemos analizar el valor como otro valor requerido (es decir, con un solo tipo). Solo tenga en cuenta que el campo puede contener nulo si el valor original en la tabla era nulo.

Vea el fragmento de código completo:

Al leer de BigQuery, simplemente no renuncies a usar GenericRecord. A veces tendrá que realizar un análisis adicional, como en este ejemplo con NULLABLE o cuando está utilizando campos NUMÉRICOS , pero el rendimiento adicional que obtendrá valdrá un par de líneas de código más.

Para leer NULLABLE, recuerde que el tipo será una UNIÓN de dos tipos: el tipo real del campo y nulo. ¡Y cuidado con los valores nulos al leer valores!


La lectura de campos NULLABLE con BigQueryIO en Apache Beam se publicó originalmente en Google Cloud - Community on Medium, donde las personas continúan la conversación resaltando y respondiendo a esta historia.