2017-05-25 2 views
1

Gerade und einfach abfragen, ich habe die folgende Funktion, die Verwendung von Google Cloud Datastor Node.js API:Google Cloud Datastor, wie für mehr Ergebnisse

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); 
    } 
    }); 
} 

Das Datenspeicher-API-Objekt ist in der Variablen this.datastore;

Das Ziel dieser Funktion ist alle Ergebnisse für eine bestimmte Abfrage, ungeachtet aller Grenzen für die Anzahl der Artikel pro Einzel runQuery Aufruf zurückgegeben zu holen.

Ich habe noch nicht über irgendwelche bestimmten harten Grenzen auferlegt durch den Datenspeicher-API auf das herausgefunden und die Dokumentation scheint in diesem Punkt etwas undurchsichtig, aber ich merkte nur, dass ich immer results[1] = { moreResults: 'MORE_RESULTS_AFTER_LIMIT' } bekommen, darauf hinweist, dass es sind noch mehr Ergebnisse zu holen, und die results[1].endCursor bleibt auf konstanten Wert stecken, die bei jeder Iteration erneut weitergegeben wird.

Also, einige einfache Abfrage, die ich in diese Funktion einstecken, fahre ich nur weiter auf die Abfrage iterativ, setzen Sie die Abfrage Start-Cursor (query.start(queryCursor);) auf die endCursor im Ergebnis der vorherigen Abfrage erhalten. Und ich hoffe natürlich, dass ich bei jeder Iteration die nächsten Ergebnisse erhalten kann. Aber ich bekomme immer den gleichen Wert für results[1].endCursor. Meine Frage ist: Warum?

// 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]; 
    }); 
} 

(mit Ausnahme der Tatsache, dass ich von mir nicht eine Grenze für die Größe des Abfrageergebnisses angeben, was ich habe auch:

Konzeptionell kann ich keinen Unterschied zu this example given in the Google Documentation sehen versucht, indem Sie es auf 1000, die nichts ändert.)

Warum läuft mein Code in diese Endlosschleife, stecken auf jedem Schritt auf dem gleichen "endCursor"? Und wie korrigiere ich das?

Auch, was ist die harte Grenze für die Anzahl der Ergebnisse pro Anruf von ? Ich habe diese Informationen bisher nicht in der Google Datastore-Dokumentation gefunden.

Danke.

Antwort

3

Mit Blick auf die API documentation für die Node.js-Client-Bibliothek für Datastore gibt es einen Abschnitt auf dieser Seite mit dem Titel "Paginieren von Datensätzen", die Ihnen helfen können. Hier ist eine direkte Kopie des Code-Schnipsel aus dem Bereich:

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); 
    }); 
}); 

Vielleicht können Sie versuchen, eine der anderen Syntaxoptionen verwendet (anstelle von Promises). Die Methode runQuery kann eine Callback-Funktion als Argument verwenden, und die Parameter dieses Callbacks enthalten explizite Verweise auf das Array entities und das info-Objekt (das den endCursor als Eigenschaft hat).

Außerdem gibt es Beschränkungen und Kontingente für Aufrufe der Datastore-API. Hier sind Links zu offiziellen Dokumenten, die sie im Einzelnen behandelt:

Limits

Quotas

+0

Vielen Dank für Ihre Mühe. Wie auch immer, dieses Beispiel würde in die gleiche Art von Endlosschleife laufen, über die ich verwirrt war. Es ist genau dieselbe Logik, soweit die rekursive Abfrage geht. – trollkotze

+0

Nach einigem Suchen habe ich das Problem gefunden, dass 'NO_MORE_RESULTS' tatsächlich nie zurückgegeben werden kann, auch wenn es keine Ergebnisse mehr gibt. Also würde diese Schleife für immer weitergehen, wie in meinem Fall. Stattdessen wird 'MORE_RESULTS_AFTER_LIMIT' zurückgegeben, obwohl keine weiteren Ergebnisse vorliegen. Aber 'MORE_RESULTS_AFTER_LIMIT' gibt nur an, dass _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _. – trollkotze

+0

Nun, ich habe es versucht. Ich neige dazu, die Client-Bibliotheken zu vermeiden und die REST-API direkt zu nutzen. Vielleicht können Sie das als eine Option versuchen. –

Verwandte Themen