2016-03-02 6 views
7

Zur Zeit habe ich den folgenden Code die Ergebnisse von zwei AbfragenWie bekomme ich mit pg-promise Ergebnisse aus mehreren Abfragen gleichzeitig?

dbro.many("SELECT geoname_id, country_name FROM paises WHERE locale_code=$1 LIMIT 10",data.lang) 
    .then(function(countriesData){ 
     data.countries=countriesData; 
     dbro.many("SELECT * FROM categorias") 
     .then(function(categoriesData){ 
     data.categories=(categoriesData) 
     console.log(data); 
     res.render('layout', data); 
     res.end(); 
     }) 
     .catch(function(err){ 
     console.log("error while fetching categories data"); 
     }) 
    }) 
    .catch(function(err){ 
     console.log("error while fetching countries data",err); 
    }); 

Irgendwie zu bekommen ich denke, das ist nicht richtig. Was ist, wenn ich die Ergebnisse vieler Abfragen abrufen muss, bevor ich den Rückruf zurücksende? Die Verschachtelung von mehreren then/catch wird hässlich. Das Ziel besteht darin, alle Daten vor dem Rendern einer Seite bereit zu haben (in Express)

Antwort

17

pg-promise Dokumentation hat plenty of examples wie mehrere Abfragen ausgeführt werden.

Initialisierung

const pgp = require('pg-promise')(/* initialization options */); 
const db = pgp('postgres://username:[email protected]:port/database'); 

Wenn Abfragen voneinander abhängig sind wir sollten ketten sie innerhalb einer Aufgabe:

db.task('get-user-events', t => { 
     return t.one('select * from users where id = $1', 123) 
      .then(user => { 
       return t.any('select * from events where login = $1', user.name); 
      }); 
    }) 
    .then(data => { 
     // data = result from the last query; 
    }) 
    .catch(error => { 
     // error 
    }); 

Wenn Abfragen keine Abhängigkeiten haben wir sollten führen sie als eine batch innerhalb einer Aufgabe:

db.task('get-everything', t => { 
     return t.batch([ 
      t.any('select * from users'), 
      t.one('select count(*) from events') 
     ]); 
    }) 
    .then(data => { 
     // data[0] = result from the first query; 
     // data[1] = result from the second query; 
    }) 
    .catch(error => { 
     // error 
    }); 

Und wenn die Abfragen, die Daten zu ändern, wir sollten ersetzen task mit tx für die Transaktion.

Beachten Sie, dass ich jede Aussage mit "sollte", wie Sie alles außerhalb von Aufgaben oder Transaktionen ausführen können, aber es wird nicht empfohlen, da die Datenbankverbindungen verwaltet werden.

Sie sollten Abfragen nur auf dem Stammprotokoll ausführen (db Objekt), wenn Sie eine einzelne Abfrage pro HTTP-Anforderung ausführen müssen. Mehrere Abfragen auf einmal sollten immer innerhalb von Aufgaben/Transaktionen ausgeführt werden.

Siehe auch Chaining Queries, mit seinem Hauptpunkt auf der Unterseite befindet:

Wenn Sie die empfohlene Ansatz nicht folgen, wird Ihre Anwendung unter einer kleinen Last eine bessere Leistung, durch mehr Verbindungen parallel zugeordnet, Bei hoher Last wird der Verbindungspool jedoch schnell aufgebraucht, was die Leistung und Skalierbarkeit Ihrer Anwendung beeinträchtigt.

UPDATE

von pg-promise v7.0.0 starten wir Ergebnisse aus mehreren Abfragen in einem einzigen Befehl ziehen können, die wesentlich effizienter als alle bisherigen Lösungen ist:

db.multi('SELECT * FROM users;SELECT count(*) FROM events') 
    .then(data => { 
     // data[0] = result from the first query; 
     // data[1] = result from the second query; 
    }) 
    .catch(error => { 
     // error 
    }); 

Oder wenn Sie Bluebird verwenden, dann:

db.multi('SELECT * FROM users;SELECT count(*) FROM events') 
    .spread((users, [{count}]) => { 
     // users = array of user records; 
     // count = string with the count; 
    }) 
    .catch(error => { 
     // error 
    }); 

Siehe neue Methoden multi und multiResult.

+0

Danke das ist, was ich gesucht habe.Ich habe die Dokumentation gelesen, aber ich habe den entscheidenden Teil (zumindest für mich) verpasst: \t // Daten [0] = Ergebnis aus der ersten Abfrage; // Daten [1] = Ergebnis der zweiten Abfrage; (Ergebnisdaten als Array) –

+0

@ vitaly-t Danke für Ihre Beispiele. Aber wie würdest du gehen, wenn du beide mischen müsstest? In meiner Aufgabe führe ich 5 unabhängige Abfragen aus. Jeder gibt die letzte Einfüge-ID zurück. Sobald diese Aufgabe erledigt ist, muss ich eine letzte Abfrage ausführen, die alle von der Aufgabe erzeugten IDs verwendet. Ich habe es bisher nicht geschafft, beides zu mischen. Hast du irgendeine Idee. Danke für Ihre Hilfe. – Stanislasdrg

+0

@Stanislasdrg Was Sie fragen, ist mehr über die grundlegende Verwendung von Versprechen als diese Bibliothek. Sie geben 't.batch zurück ([... Ihre 5 Einfügungen ...]). Dann (Daten => t.query (... Abfrage basierend auf Daten ...))'. –