【问题标题】:Write repeated Strings to BigQuery using Apache Beam使用 Apache Beam 将重复的字符串写入 BigQuery
【发布时间】:2021-06-04 06:46:03
【问题描述】:

我有一个包含Strings 的数据流,看起来像JSONArrays。我想解析这些字符串并使用 Apache Beam 写入 BigQuery 表,但在写入重复字符串时出现错误。

以下是我将字符串转换为 TableRow 的方法:

    String dataString = "[{\"EMAIL\": [\"zog@yahoo.com\"]}]";

    JSONArray jsonArray = new JSONArray(dataString);
    TableRow tableRow = new TableRow();

    for (int i = 0; i < jsonArray.length(); i++) {
      JSONArray emailArray = new JSONArray(jsonArray.getJSONObject(i).get("EMAIL").toString());

      tableRow.set("EMAIL", emailArray); //Results in error
    }

这是我的 BigQuery 架构的样子:

[
  {
    "name": "EMAIL",
    "type": "STRING",
    "mode": "REPEATED"
  }
]

我已经设法使用 Python 将类似的重复字符串写入 BigQuery 表,但无法使用 Apache Beam。我想我没有在TableRow 中保存正确的键值对。我现在得到的错误是:

java.io.IOException: Insert failed: [{"errors":[{"debugInfo":"","location":"email","message":"This field is not a record.","reason":"invalid"}],"index":0}]

我需要有关如何在不创建记录的情况下将类似的重复字符串保存到 BigQuery 的帮助,如果有任何建议或建议,我将不胜感激。提前致谢。

【问题讨论】:

  • 该错误消息似乎可能是因为尝试将 EMAIL 设置为不正确的值。您的dataString示例是否准确?因为如果我正确解释它,它是一个包含两个JSONObjects 的数组,第一个只定义了EMAIL 字段,第二个只定义了ValidFrom 字段。如果在写入 BQ 时 EMAIL 字段设置为 NULL,我可能会看到问题。
  • 数据字符串是准确的,是的,Daniel。但是请原谅我没有在任何地方检查元素类型的错误。由于我是在我的原始代码中检查数据类型,所以我删除了上面sn-p中不必要的代码。

标签: java google-bigquery google-cloud-dataflow apache-beam


【解决方案1】:

看来你要创建

  1. 一行包含串联字符串的电子邮件地址,或
  2. 每封电子邮件一行,或
  3. 一行有一个重复的字段。

请注意,您的 ValidFrom 字段似乎是 STRING 类型,不是重复字段,除非它包含在分层架构中的重复字段中。

在您提供的示例代码中,您正在创建一个 JSONArray 并将其放入 STRING 字段中,我认为这会导致问题,因为类型不兼容。如果您想将其保留为普通的 STRING 字段,可以使用下面的解决方案 1。

还要确保您在 BigQuery 中的列名称与您的代码中的名称相匹配,我看到您同时使用了 ValidFromEMAIL(尽管您发布的代码中可能有错误)。

方案一:一行有字符串字段

如果您想在 BigQuery 中添加 一行串联 String 字段,您可以使用以下内容:

// Initialize your final row
TableRow tableRow = new TableRow();

// Find email addresses
String [] emails = ... // your extraction logic

// Build a concatenated string of emails
String allEmails = String.join(";", emails);

// Add the string field to the row
tableRow.set('EMAILS', allEmails);

解决方案 2:带有字符串字段的多行

如果您想插入多行,您可以创建多个表格行:

// Find email addresses
String [] emails = ... // your extraction logic

// Build a row per email
for(String email: emails) {
    // Initialize your final row
    TableRow tableRow = new TableRow();
    tableRow.set('EMAIL', email);
    
    // TODO: do something with the row (add to list, or ...)
}

解决方案 3:一行包含 REPEATED 字段

如果您想在 BigQuery 中添加带有REPEATED STRING 字段的一行,您可以使用以下内容:

// Initialize your final row
TableRow tableRow = new TableRow();

// Find email addresses
String [] emails = ... // your extraction logic

// Build the repeated field
List<String> emailCells = new ArrayList<>();
for(String email: emails) {
    emailCells.add(email);
}

// Add the repeated field to the row
tableRow.set('EMAILS', emailCells);

如果这不是您的目标,请提供更多详细信息。

【讨论】:

  • 非常感谢@Jonny5 的详细回答。我使用了解决方案 3 并成功地将重复的字符串写入 BigQuery。感谢您的帮助。
猜你喜欢
  • 2020-12-21
  • 2021-03-25
  • 1970-01-01
  • 2018-11-18
  • 2019-03-26
  • 2022-06-27
  • 2020-03-31
  • 2017-12-15
相关资源
最近更新 更多