【问题标题】:Can I append data to an existing BigQuery table from a CSV file using the API?我可以使用 API 将数据从 CSV 文件附加到现有 BigQuery 表吗?
【发布时间】:2017-03-27 07:19:36
【问题描述】:

我正在尝试使用 Google Apps 脚本通过 BigQuery API 将数据附加到 BigQuery 表中。要附加的数据当前是 CSV 格式。到目前为止,我发现您可以使用tabledata().insertAll()stream data into BigQuery,但它看起来需要 json 格式,我什至不相信它会做我需要做的事情。我缺少一个直接的解决方案吗?因为我知道 BigQuery 支持追加,但我发现的所有内容都真正专注于将数据加载到新表中。

编辑: 听起来tabledata().insertAll() 确实是正确的使用方法(希望如此)。所以我将我的文件转换为 json,但现在我被困在如何实际使用它上。我正在尝试根据reference page for it 来确定我正在做的事情,但这对我来说仍然很困惑。目前,当我运行我的代码并遇到fetch 调用时,我收到404 错误。我正在尝试获取 URL,也许这不是我应该做的事情?我对 API 真的很陌生,我仍在弄清楚它们是如何工作的。这是我目前拥有的导致此问题的代码:

var tableId = 'users';
var file = DriveApp.getFileById(jsonId);
//I don't know if a blob is the type that I want or not, but I'm trying it
var data = file.getBlob();

var url = 'https://www.googleapis.com/bigquery/v2/projects/PROJECT_ID/datasets/DATASET_ID/tables/tableId/insertAll'
.replace("PROJECT_ID", params.PROJECT_ID)
.replace("DATASET_ID", params.DATASET_ID)
.replace("tableId", tableId);

var response = UrlFetchApp.fetch(url, {
"kind": "bigquery#tableDataInsertAllRequest",
"skipInvalidRows": 0,
"ignoreUnknownValues": 0,
"rows": [
  {
    "json": data
  }
],
headers: {
  Authorization: 'Bearer ' + service.getAccessToken()
}
});


var result = JSON.parse(response.getContentText());
Logger.log(JSON.stringify(result, null, 2));

【问题讨论】:

  • 您已经确定了方法,将数据转换为正确的格式只是解析csv并将其编码为JSON的问题,您在哪一步遇到问题?你已经尝试过什么
  • 那么insertAll() 方法确实是我想要的吗?然后我的问题是找到一种体面的方法将 CSV 文件转换为 json(最好使用 Google Apps 脚本)我猜。加上实际上弄清楚函数调用是如何工作的。我真的怀疑这是否是我正在寻找的正确方法。
  • 好的,我想我现在有 json 格式的数据(希望是正确的)。不过,从这里开始,我正在努力实际调用 API。我现在可以用更多细节更新我的问题。
  • Google Apps 脚本可以启用 BigQuery API 而无需进行提取,您只需在开发者控制台中激活并启用即可。看看我的回答。

标签: google-apps-script google-api google-bigquery


【解决方案1】:

这不是从 csv 到 BQ JSON 最直接的方法,但它是我正在使用的一些代码,应该可以在 BigQuery 方面为您提供帮助。

var PROJECT_ID = "xxx";
var DATASET_ID = "yyy";
function convertValuesToRows(data) {
  var rows = [];  
  var headers = data[0];

  for (var i = 1, numColumns = data.length; i < numColumns; i++) {
    var row = BigQuery.newTableDataInsertAllRequestRows();
    row.json = data[i].reduce(function(obj, value, index) {
      obj[headers[index]] = value;
      return obj
    }, {});
    rows.push(row);
  }; 
  return rows;
}

function bigqueryInsertData(data, tableName) {
  var insertAllRequest = BigQuery.newTableDataInsertAllRequest();
  insertAllRequest.rows = convertValuesToRows(data);
  var response = BigQuery.Tabledata.insertAll(insertAllRequest, PROJECT_ID, DATASET_ID, tableName);
  if (response.insertErrors) {
    Logger.log(response.insertErrors);
  }
}

这允许您提供任何 GAS 样式值矩阵(来自 getValues 或实际上是 Utilities.parseCsv

convertValuesToRows 将采用二维字符串数组(带有标题)并将其编码为 BigQuery 所需的格式,例如

[["H1", "H2", "H3"],
 [1   , 2   , 3   ],
 [4   , 5   , 6   ]];

将以键值对的形式添加到 insertRows 请求中,即

[{H1: 1, H2: 2, H3: 3},
 {H1: 4, H2: 5, H3: 6}]

您只需要担心第一个表示,因为这是您传递给 bigQueryInsertData 的内容以及您想要将数据输入到的表名(表的架构需要与您发送的内容相匹配)和转换器函数是从内部调用的。

Utilities.parseCsv 已经返回了一个二维字符串数组,所以你基本上可以调用bigQueryInsertData(Utilities.parseCsv(data.getDataAsString()), "myTable")

【讨论】:

  • 我不知道如何利用您的答案。我试图了解我在这里看到的内容,但我有点困惑。你能解释一下这段代码在做什么吗?我是否以某种方式将 json 解析为单独的行以一次插入一个?是否有关于 API 脚本版本的文档?我要做的就是在脚本中自动完成。
  • 请看我更新的答案,希望能把事情弄清楚一点。启用 BigQuery API 后,您应该能够按原样使用该函数
  • 非常感谢您的帮助!我的代码运行时没有抛出错误并声称运行成功,但我还没有看到 BigQuery 上实际发生的任何数据更新。我认为注册更改可能需要几分钟,但我一直在等待和刷新,但没有运气,所以很难说一切是否正常。如果我的代码没有抱怨但实际上并没有完成它的工作,那么问题将是什么?我已经记录了进度,所以我看到你的函数正在执行...... Idk 也许在一小时内 BigQuery 会显示它确实有效。
  • 插入应该是可以立即查询的,你检查执行日志看是否有插入错误?
  • 没有错误,而且我添加了更多日志语句以确保事情正在实际执行(它们是),因此我感到困惑......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-09-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-14
  • 2020-12-26
相关资源
最近更新 更多