简体   繁体   English

BigQuery + PHP客户端中的令牌分页不起作用

[英]Pagination with token in BigQuery + PHP client not working

I'm trying to implement a simple pagination mechanism with BigQuery. 我正在尝试使用BigQuery实现简单的分页机制。

this is my query function: 这是我的查询功能:

function query($sql, $max_results = null, $page_token = null) {
    $request = new Google_Service_Bigquery_QueryRequest();
    $request->setQuery($sql);
    $response = $this->service->jobs->query(PROJECT_ID, $request);
    $job_id = $response->getJobReference()->getJobId();

    $optParams = ($max_results) ? array(
        'pageToken' => $page_token,
        'maxResults' => $max_results,
    ) : array();
    $response = $this->service->jobs->getQueryResults(PROJECT_ID, $job_id, $optParams);
    if (!$response->getJobComplete()) {
        return null;
    }
    $rowsJson = $this->rowsJson($response->getRows());
    if ($max_results) {
        return array(
            "rows" => $rowsJson,
            "token" => $response->getPageToken()
        );
    }
    return $rowsJson;
}

query("select url, CEIL(AVG(total)) as avg, count(id) as count from $table_id " .
      "where created > $date_start and created < $date_end group by url order by $order_by desc",
      10, $page_token
);

The first query seems like it's working. 第一个查询似乎正在运行。 it returns only 10 results and a token (there are definitely more than 10 results). 它仅返回10个结果和一个令牌(肯定有10个以上的结果)。 But when I call the function later with the token I got, the results are empty... I have no idea why. 但是,当我稍后使用获得的令牌调用该函数时,结果为空……我不知道为什么。 I see no error message in the logs or anything... 我在日志或任何内容中都没有看到错误消息...

In order for BigQuery "pagination" to work you shold follow below steps (simplified but enough for this answer): 为了使BigQuery“分页”正常工作,请按照以下步骤操作(已简化,但足以满足此答案):

  1. Execute query job 执行查询作业
  2. Retrieve jobid 检索工作ID
  3. Execute getQueryResults with that jobid and retrieve result and page_token 使用该jobid执行getQueryResults并检索结果和page_token
  4. If page_token null - you done, otherwise continue with next step 如果page_token为空-您已完成,否则继续下一步
  5. Execute getQueryResults ( still with jobid from #2 ) and retrieve result and page_token 执行getQueryResults( still with jobid from #2 )并检索结果和page_token
  6. Jump to step #4 跳至步骤4

Now, you most likely will see that your code doesn't follow this and each time executes query as new job - which totally breaks condition highlighted in #5 ( still with jobid from #2 ). 现在,您很可能会发现您的代码没有遵循此要求,而是每次将查询作为新任务执行-完全破坏了#5中突出显示的条件( still with jobid from #2 )。

The reason why first time it returns result is that first call actually meet above steps, but in consequitive calls you actually passing page_token and force execution of NEW job with some arbitrary (from that new job prospective) page_token 第一次返回结果的原因是第一次调用实际上满足了上述步骤,但是在随后的调用中,您实际上传递了page_token并强制执行带有任意(来自预期的新作业)page_token的新作业
And also, this explains why your current code works with startIndex 而且,这也解释了为什么您当前的代码可以与startIndex一起使用

Try to rewrite your code to follow above steps and it should work 尝试重写您的代码以按照上述步骤操作,它应该可以工作

Also, 也,
PS page_token is alive and should be reusable for as long as underlying temp table (that holds your result) is alive - which is approximately 24 hours PS page_token处于活动状态,并且只要底层临时表(用于保存您的结果)处于活动状态,则应可重复使用-大约24小时

Solved it by using startIndex instead of tokens. 通过使用startIndex而不是令牌解决了它。

Maybe tokens are short-lived and don't survive the 4-5 seconds delay, I'm not really sure. 我不确定令牌可能是短命的,并且不能在4-5秒的延迟中幸免。

Using a page token to get paged results are recommended because page token provides a view of the table at the first time it is retrieved. 推荐使用页面令牌来获取分页结果,因为页面令牌在首次检索表时会提供该表的视图。 By just using startIndex, you may see different results as the table may change. 通过仅使用startIndex,您可能会看到不同的结果,因为表可能会更改。

Response size is what may cause you get less than maxResults. 响应大小可能会导致您获得的结果少于maxResults。 We are limited by Apiary to return results of certain size. 养蜂场限制我们返回一定大小的结果。 https://cloud.google.com/bigquery/docs/data#paging And we also have a max field counts to be less than 350,000 limit per call. https://cloud.google.com/bigquery/docs/data#paging而且我们每次呼叫的最大字段数也少于350,000。

You should try to get the next results by using the page token it passed back to you. 您应该尝试使用传递回给您的页面令牌来获得下一个结果。

function get_quote($page = 1){
global $database_connection;
    $start = 0;
    $limit = 5;
    $start = ($page - 1) * $limit;

    //select from database with limit $start, $limit
    //display results

    $sql_get_quote =  "SELECT * FROM quote_table ORDER BY date_added ASC LIMIT $start, $limit";
    $query_get_quote = mysqli_query($database_connection, $sql_get_quote);
    while($fetch_quote = mysqli_fetch_array($query_get_quote)){
        echo "<br>
        <div class='w3-container w3-pale-green w3-bottombar w3-border-green w3-border'>
        <p>".$fetch_quote['quote']."</p><hr><p class='w3-left-align'>".$fetch_quote['quote_by']."</p>
        </div>";
    }

    //do another query, get the num_rows
    $quote_rows= mysqli_num_rows (mysqli_query($database_connection ,"SELECT * FROM quote_table"));
    $total = ceil($quote_rows / $limit);
if (isset($page)){
    echo "<div class='w3-container'>";
    echo "<ul class='pager'>";
    if($page > 1) {
        echo "<a href='?page=".($page - 1)."' style='float: left;' class=' w3-sand w3-btn w3-margin w3-round'>Previous</a>";
    }
    for($i = 1; $i <= $total; $i++) {
        if($i == $page) { echo "<li class='active current'>".$i."</li>"; }

        else { echo "<li><a href='?page=".$i."'>".$i."</a></li>"; }
    }
    if($page != $total) {
        echo "<a href='?page=".($page + 1)."' class='w3-btn w3-margin w3-sand w3-round'>Next</a>";
    }
    echo "</ul></div>";
}

} }

This works for me... Hope you can build around this 这对我有用...希望您可以在此基础上建立

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM