如何正确迭代所有BigQuery结果行?

时间:2017-08-25 11:27:37

标签: java google-api google-bigquery

我从BigQuery表中选择一列,如

select url from `project.dataset.urllist` where status = 2

计数(*)给了我245217个结果,我可以查询这个行数 浏览器控制台。

根据示例在Java中实现相同的 https://cloud.google.com/bigquery/create-simple-app-api看起来像

QueryResponse response = bigquery.query(queryRequest);
QueryResult result = response.getResult();

while (result != null) {
  for (List<FieldValue> row : result.iterateAll()) {
    ... do something
  }
  result = result.getNextPage();
}

但是我最终得到了3个QueryResult页面返回的435651个结果行。

我发现在while循环的第一次迭代中我已经得到了 所需的245217行;第二次和第三次迭代返回一部分 再次得到相同的结果。 如果没有while循环,我会收到我的期望,但这是正确的吗?

QueryResult result = response.getResult();
for (List<FieldValue> row : result.iterateAll()) {
  ... do something
}

显然,第一个结果页面包含#1到#245217的所有行, 第二页包含#100000到#245217的行, 第三页包含#200000到#245217的行。 这是API中的Bug吗?

1 个答案:

答案 0 :(得分:3)

从实际角度来看,关于如何正确迭代所有BigQuery行的简短答案似乎是:

  • 仅依靠当前版本的Google Cloud Java Client Core(1.4.0)和BigQuery(0.22.0-beta)中的QueryResult#iterateAll();并通过结果页面删除该外部循环。

考虑

让我们来看看iterateAllQueryResult继承的com.google.cloud.PageImpl方法的实现。目前,此方法返回一个Iterator,它从当前页面开始,并且一旦迭代了当前页面的所有元素(github link),似乎就会获取下一页。这是在相应的computeNext()调用时发生的,其中currentPage = currentPage.getNextPage();明确发生

也就是说,result.getNextPage().iterateAll()返回Iterator,它从getNextPage返回的页面的第一个元素开始迭代元素,并将迭代所有下一页,直到到达最后一页的最后一个元素。与result.iterateAll()的唯一区别在于,最后一个返回Iterator从第一页开始。

根据上述内容,将result.iterateAll()调用包裹到页面中的附加循环是多余的,因此看起来current version of example不是100%一致并且需要删除周围的循环

while (result != null) {
  ...
  result = result.getNextPage();
}

就API本身的一致性而言 - 由于我们既没有替代iterateAll特定页面上的特定行,也没有能力,因此缺乏以每页为基础处理结果的明确方法。清楚地标识到达当前页面的末尾(迭代时手动计算行的能力除外)。但是,当通过所有行处理整个结果时 - 这似乎不是阻止者

修改

请注意,Java Client for BigQuery目前处于测试阶段,并且有明确说明:

  

注意:此客户端正在进行中,可能偶尔会进行向后兼容的更改。

这意味着我们应该期待进一步的变化,并相应地调整处理所有行的方法。