PostgreSQL
 sql >> Database >  >> RDS >> PostgreSQL

ottieni la tabella JOIN come matrice di risultati con PostgreSQL/NodeJS

Questo è facile da fare con pg-promise:

function buildTree(t) {
    const v = q => t.any('SELECT id, value FROM votes WHERE question_id = $1', q.id)
        .then(votes => {
            q.votes = votes;
            return q;
        });

    return t.map('SELECT * FROM questions', undefined, v).then(a => t.batch(a));
}

db.task(buildTree)
    .then(data => {
        console.log(data); // your data tree
    })
    .catch(error => {
        console.log(error);
    });

Come sopra, ma usando ES7 async /await sintassi:

await db.task(async t => {
    const questions = await t.any('SELECT * FROM questions');
    for(const q of questions) {
        q.votes = await t.any('SELECT id, value FROM votes WHERE question_id = $1', [q.id]);
    }
    return questions;
});
// method "task" resolves with the correct data tree

API:mappa, qualsiasi, attività, batch

Domande correlate:

  • Prendi un albero genitori + figli con pg-promise
  • Attività condizionale con pg-promise

E se vuoi usare solo una singola query, usando PostgreSQL 9.4 e versioni successive puoi fare quanto segue:

SELECT json_build_object('id', q.id, 'content', q.content, 'votes',
    (SELECT json_agg(json_build_object('id', v.id, 'value', v.value))
     FROM votes v WHERE q.id = v.question_id))
FROM questions q

E poi il tuo esempio di pg-promise sarebbe:

const query =
    `SELECT json_build_object('id', q.id, 'content', q.content, 'votes',
        (SELECT json_agg(json_build_object('id', v.id, 'value', v.value))
         FROM votes v WHERE q.id = v.question_id)) json
    FROM questions q`;
    
const data = await db.map(query, [], a => a.json);

E sicuramente vorrai mantenere query così complesse in file SQL esterni. Vedi File di query.

Conclusione

La scelta tra i due approcci presentati sopra dovrebbe essere basata sui requisiti di prestazione della tua applicazione:

  • L'approccio a query singola è più veloce, ma è alquanto difficile da leggere o estendere, essendo piuttosto dettagliato
  • L'approccio multi-query è più facile da comprendere ed estendere, ma non è ottimo per le prestazioni, a causa del numero dinamico di query eseguite.

AGGIORNAMENTO-1

La seguente risposta correlata offre più opzioni, concatenando le query figlie, che offriranno prestazioni molto migliorate:combina le query del ciclo nidificato con il risultato padre pg-promise.

AGGIORNAMENTO-2

È stato aggiunto un altro esempio, utilizzando ES7 async /await approccio.