Как импортировать CSV-файл в таблицу BigQuery без каких-либо имен столбцов или схемы?
в настоящее время я пишу утилиту Java для импорта нескольких CSV-файлов из GCS в BigQuery. Я могу легко достичь этого с помощью bq load
, но я хотел сделать это с помощью задания потока данных. Поэтому я использую конвейер потока данных и Pardo transformer (возвращает TableRow, чтобы применить его к BigQueryIO), и я создал StringToRowConverter () для преобразования. Здесь начинается фактическая проблема - я вынужден указать схему для целевой таблицы, хотя я не хочу создавать новую таблицу, если она не существует - только пытается загрузить данные. Поэтому я не хочу вручную устанавливать имя столбца для TableRow, поскольку у меня есть около 600 столбцов.
public class StringToRowConverter extends DoFn<String, TableRow> {
private static Logger logger = LoggerFactory.getLogger(StringToRowConverter.class);
public void processElement(ProcessContext c) {
TableRow row = new TableRow();
row.set("DO NOT KNOW THE COLUMN NAME", c.element());
c.output(row);
}
}
кроме того, предполагается, что таблица уже существует в наборе данных BigQuery, и мне не нужно ее создавать, а также CSV-файл содержит столбцы в правильном порядке.
Если нет обходного пути к этому сценарию, и имя столбца необходимо для загрузки данных, то я могу иметь его в первой строке CSV файл.
любая помощь будет оценили.
1 ответов
чтобы избежать создания таблицы, следует использовать BigQueryIO.Писать.CreateDisposition.CREATE_NEVER из BigQueryIO.Запись во время конфигурации конвейера. Источник: https://cloud.google.com/dataflow/java-sdk/JavaDoc/com/google/cloud/dataflow/sdk/io/BigQueryIO.Write
вам не нужно знать схему таблицы BigQuery заранее, вы можете обнаружить ее динамически. Например, вы можете использовать API BigQuery (https://cloud.google.com/bigquery/docs/reference/rest/v2/tables/get) для запроса схемы таблицы и передачи ее в качестве параметра для класса StringToRowConverter. Другой вариант, предполагающий, что первая строка является заголовком, - пропустить первую строку и использовать ее для правильного отображения остальной части файла.
приведенный ниже код реализует второй подход, а также настраивает выходные данные для добавления в существующую таблицу BigQuery.
public class DFJob {
public static class StringToRowConverter extends DoFn<String, TableRow> {
private String[] columnNames;
private boolean isFirstRow = true;
public void processElement(ProcessContext c) {
TableRow row = new TableRow();
String[] parts = c.element().split(",");
if (isFirstRow) {
columnNames = Arrays.copyOf(parts, parts.length);
isFirstRow = false;
} else {
for (int i = 0; i < parts.length; i++) {
row.set(columnNames[i], parts[i]);
}
c.output(row);
}
}
}
public static void main(String[] args) {
DataflowPipelineOptions options = PipelineOptionsFactory.create()
.as(DataflowPipelineOptions.class);
options.setRunner(BlockingDataflowPipelineRunner.class);
Pipeline p = Pipeline.create(options);
p.apply(TextIO.Read.from("gs://dataflow-samples/myfile.csv"))
.apply(ParDo.of(new StringToRowConverter()))
.apply(BigQueryIO.Write.to("myTable")
.withCreateDisposition(BigQueryIO.Write.CreateDisposition.CREATE_NEVER)
.withWriteDisposition(BigQueryIO.Write.WriteDisposition.WRITE_APPEND));
PipelineResult result = p.run();
}
}