Jest to łatwe z 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);
});
To samo co powyżej, ale przy użyciu ES7 async
/await
składnia:
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:mapa, dowolne, zadanie, wsad
Powiązane pytania:
- Zdobądź drzewo rodziców + dzieci z obietnicą pg
- Warunkowe zadanie z pg-obietnicą
A jeśli chcesz użyć tylko jednego zapytania, używając składni PostgreSQL 9.4 i nowszych, możesz wykonać następujące czynności:
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
A wtedy twój przykład obietnicy pg będzie wyglądał następująco:
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);
I na pewno będziesz chciał przechowywać tak złożone zapytania w zewnętrznych plikach SQL. Zobacz Pliki zapytań.
Wniosek
Wybór między dwoma przedstawionymi powyżej podejściami powinien opierać się na wymaganiach wydajności aplikacji:
- Podejście z jednym zapytaniem jest szybsze, ale nieco trudne do odczytania lub rozszerzenia, ponieważ jest dość szczegółowe
- Podejście oparte na wielu zapytaniach jest łatwiejsze do zrozumienia i rozszerzenia, ale nie jest dobre dla wydajności ze względu na dynamiczną liczbę wykonywanych zapytań.
AKTUALIZACJA-1
Poniższa powiązana odpowiedź oferuje więcej opcji, łącząc zapytania podrzędne, co daje znacznie lepszą wydajność:Połącz zapytania zagnieżdżonej pętli z wynikiem nadrzędnym pg-promise.
AKTUALIZACJA-2
Dodano kolejny przykład, używając ES7 async
/await
podejście.