La mejor manera de consultar una relación de muchos a muchos usando pg-promise

Por ejemplo, quiero obtener la información del usuario, los correos electrónicos y sus roles de db y crear un objeto como:

{ "id": 1, "firstname": "John", "lastname": "Johnny", "emails": [ { "type": "work", "email": "work@work.com" }, { "type": "personal", "email": "personal@personal.com" } ], "roles": [ { "role": "ADM", "title": "Admin" }, { "role": "PUB", "title": "Publisher" } ] } 

Hay tres tablas que necesito consultar:

  • Users tabla de Users tiene id , nombre, lastname .
  • Emails tabla de Emails tiene type , email , user_id .
  • Roles tabla de Roles tiene role , title , user_id .

Basado en la wiki de pg-promise , estoy casi seguro de que se debe hacer usando Tareas pero no estoy seguro de cómo los encadenarías.

ACTUALIZACIÓN En mi proyecto real tuve que insertar un producto y usar la identificación generada para insertar atributos. Agregando mi código aquí en caso de que tenga una situación similar:

 //Insert a new product with attribites as key value pairs post_product_with_attr: function(args) { return db.task(function(t) { return t.one(sql.post_new_product, args) .then(function(dt) { var queries = []; Object.keys(args).forEach(function(key) { queries.push(t.one(sql.post_attr_one, { Id: dt.id, key: key, value: args[key] })); }); return queries.length ? t.batch(queries) : [dt]; }); }); } 

Lo que estás describiendo no es una relación de muchos a muchos, es una relación de dos a muchos.

Basado en la wiki de pg-promise , estoy casi seguro de que se debe hacer usando Tareas pero no estoy seguro de cómo los encadenarías.

En tu ejemplo no hay necesidad de encadenar nada. Uno encadena promesas cuando el resultado de uno debe usarse como criterio para el siguiente, porque así es como funcionan las promesas, no solo las consultas.

Por eso, puede ejecutar las 3 consultas en paralelo, como un lote.

El siguiente ejemplo utiliza pg-promise con Bluebird como la biblioteca de promesas:

 function getUserInfo(userId) { return db.task(t=>t.batch([ t.one('SELECT id, firstname, lastname FROM Users WHERE id = $1', userId), t.any('SELECT type, email FROM Emails WHERE user_id = $1', userId), t.any('SELECT role, title FROM Roles WHERE user_id = $1', userId) ])) .spread((user, emails, roles)=> { user.emails = emails; user.roles = roles; return user; }) } 

Ejemplo de uso:

 getUserInfo(123) .then(info=> { // info = object as described in the question; }) .catch(error=> { // error; });