2017-05-25 112 views
1

直而簡單,我有以下功能,使用谷歌雲存儲API的Node.js:谷歌雲存儲,如何查詢更多結果

fetchAll(query, result=[], queryCursor=null) { 
    this.debug(`datastoreService.fetchAll, queryCursor=${queryCursor}`); 
    if (queryCursor !== null) { 
    query.start(queryCursor); 
    } 
    return this.datastore.runQuery(query) 
    .then((results) => { 
    result=result.concat(results[0]); 
    if (results[1].moreResults === _datastore.NO_MORE_RESULTS) { 
     return result; 
    } else { 
     this.debug(`results[1] = `, results[1]); 
     this.debug(`fetch next with queryCursor=${results[1].endCursor}`); 
     return this.fetchAll(query, result, results[1].endCursor); 
    } 
    }); 
} 

的數據存儲API對象是在變量this.datastore;

該功能的目標是針對給定查詢獲取全部結果,儘管對每個runQuery調用返回的項目數量有任何限制。

我還沒有發現有關這個數據存儲API強加的任何明確的硬性限制,以及文件似乎在這一點上有點不透明的,但我只注意到我總是得到 results[1] = { moreResults: 'MORE_RESULTS_AFTER_LIMIT' }, 表明有仍然有更多的結果被提取,並且results[1].endCursor仍然停留在每次迭代中再次傳遞的常量值上。

因此,給我一個簡單的查詢插入這個函數,我只是繼續迭代運行查詢,設置查詢開始光標(通過執行query.start(queryCursor);)到前面查詢的結果中獲得的endCursor。顯然,我的希望是在本次迭代中的每個連續查詢中獲得下一批結果。但我總是得到相同的價值results[1].endCursor。我的問題是:爲什麼?

概念,我不能看到this example given in the Google Documentation一個區別:

// By default, google-cloud-node will automatically paginate through all of 
// the results that match a query. However, this sample implements manual 
// pagination using limits and cursor tokens. 
function runPageQuery (pageCursor) { 
    let query = datastore.createQuery('Task') 
    .limit(pageSize); 

    if (pageCursor) { 
    query = query.start(pageCursor); 
    } 

    return datastore.runQuery(query) 
    .then((results) => { 
     const entities = results[0]; 
     const info = results[1]; 

     if (info.moreResults !== Datastore.NO_MORE_RESULTS) { 
     // If there are more results to retrieve, the end cursor is 
     // automatically set on `info`. To get this value directly, access 
     // the `endCursor` property. 
     return runPageQuery(info.endCursor) 
      .then((results) => { 
      // Concatenate entities 
      results[0] = entities.concat(results[0]); 
      return results; 
      }); 
     } 

     return [entities, info]; 
    }); 
} 

(除了事實,我不通過自己對查詢結果的大小指定限制,這我也有嘗試,通過將其設置爲1000,這不會改變任何東西)。

爲什麼我的代碼運行到這個無限循環,堅持在每個步驟在相同的「endCursor」?我該如何糾正這一點?

此外,每次電話datastore.runQuery()獲得的結果數量的硬性限制是多少?到目前爲止,我還沒有在Google Datastore文檔中找到這些信息。

謝謝。

回答

3

查看數據存儲的Node.js客戶端庫的API documentation,該頁面上有一個標題爲「分頁記錄」的部分,可以幫助您。下面是從節中的代碼段直接拷貝:

var express = require('express'); 
var app = express(); 

var NUM_RESULTS_PER_PAGE = 15; 

app.get('/contacts', function(req, res) { 
    var query = datastore.createQuery('Contacts') 
    .limit(NUM_RESULTS_PER_PAGE); 

    if (req.query.nextPageCursor) { 
    query.start(req.query.nextPageCursor); 
    } 

    datastore.runQuery(query, function(err, entities, info) { 
    if (err) { 
     // Error handling omitted. 
     return; 
    } 

    // Respond to the front end with the contacts and the cursoring token 
    // from the query we just ran. 
    var frontEndResponse = { 
     contacts: entities 
    }; 

    // Check if more results may exist. 
    if (info.moreResults !== datastore.NO_MORE_RESULTS) { 
     frontEndResponse.nextPageCursor = info.endCursor; 
    } 

    res.render('contacts', frontEndResponse); 
    }); 
}); 

也許你可以嘗試使用其他語法選項之一(而非承諾)。 runQuery方法可以將回調函數作爲參數,並且該回調的參數包括對實體數組和信息對象(將endCursor作爲屬性)的顯式引用。

而且對調用Datastore API也有限制和配額。這裏是鏈接到官方文件是解決這些問題的詳細:

Limits

Quotas

+0

感謝你的努力。然而,就目前而言,這個例子會遇到與我一直困惑的同樣的無限循環。就遞歸查詢而言,它完全是一樣的邏輯。 – trollkotze

+0

經過一番搜索後,我發現問題是,即使沒有更多結果,實際上也不會返回「NO_MORE_RESULTS」。所以這個循環會永遠持續下去,就像我的情況一樣。 取而代之,雖然沒有更多結果,但會返回「MORE_RESULTS_AFTER_LIMIT」。但是'MORE_RESULTS_AFTER_LIMIT'只表明可能會有更多的結果。另外還需要檢查是否返回了空數組結果,以便在必要時中止。 – trollkotze

+0

好吧,我試過了。我傾向於避免使用客戶端庫並直接利用REST API。也許你可以嘗試作爲一種選擇。 –