Điều này rất dễ thực hiện với 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);
});
Tương tự như trên, nhưng sử dụng ES7 async
/ await
cú pháp:
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:bản đồ, bất kỳ, tác vụ, lô
Các câu hỏi liên quan:
- Nhận một cây cha mẹ + con cái với lời hứa pg
- Nhiệm vụ có điều kiện với pg-promise
Và nếu bạn chỉ muốn sử dụng một truy vấn duy nhất, thì sử dụng cú pháp PostgreSQL 9.4 trở lên, bạn có thể thực hiện như sau:
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
Và sau đó ví dụ pg-promise của bạn sẽ là:
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);
Và bạn chắc chắn sẽ muốn giữ các truy vấn phức tạp như vậy trong các tệp SQL bên ngoài. Xem Tệp truy vấn.
Kết luận
Sự lựa chọn giữa hai cách tiếp cận được trình bày ở trên phải dựa trên các yêu cầu về hiệu suất của ứng dụng của bạn:
- Phương pháp truy vấn đơn nhanh hơn, nhưng hơi khó đọc hoặc khó mở rộng, khá dài dòng
- Cách tiếp cận đa truy vấn dễ hiểu và dễ mở rộng hơn, nhưng nó không hiệu quả đối với hiệu suất do số lượng truy vấn động được thực thi.
CẬP NHẬT-1
Câu trả lời có liên quan sau đây cung cấp nhiều tùy chọn hơn, bằng cách nối các truy vấn con, điều này sẽ mang lại hiệu suất được cải thiện nhiều:Kết hợp các truy vấn vòng lặp lồng nhau với kết quả chính là pg-promise.
CẬP NHẬT-2
Một ví dụ khác được thêm vào, sử dụng ES7 async
/ await
cách tiếp cận.