2016-04-13 25 views
0

Db'de 3 varlığım var. Panolar, Listeler ve Kartlar. Bir çok ilişki var. Panolar Listeler içerir, Listeler Kartlar içerir.PostgreSQL'de iç içe JSON almak için sorguyu nasıl basitleştirebilirim?

Kurulları:

CREATE TABLE boards(
    id serial PRIMARY KEY, 
    title text NOT NULL 
); 
CREATE TABLE boards_lists(
    board_id integer NOT NULL REFERENCES boards ON DELETE RESTRICT, 
    list_id integer PRIMARY KEY REFERENCES lists ON DELETE CASCADE 
); 

Listeler:

CREATE TABLE lists(
    id serial PRIMARY KEY, 
    title text NOT NULL 
); 
CREATE TABLE lists_cards(
    list_id integer NOT NULL REFERENCES lists ON DELETE RESTRICT, 
    card_id integer PRIMARY KEY REFERENCES cards ON DELETE CASCADE 
); 

Kartlar: Örneğin

CREATE TABLE cards(
    id serial PRIMARY KEY, 
    text text NOT NULL 
); 

, ben 2 yolları var:

1. GET/panoları - panoları, listeler ve kartların

[ 
{ 
    id: 1, 
    title: 'board 1', 
    lists: [ 
    { 
     id: 1, 
     title: 'list 1', 
     cards: [ 
     { 
      id: 1, 
      text: 'card 1' 
     } 
     ] 
    } 
    ] 
} 
] 

2. GET/listeleri ile derin iç içe JSON dönmelidir - Ben panoları olmadan, yukarıda açıklandığı gibi aynı JSON geri dönmelidir sadece kartlarla listeler.

Yani, db içindeki tüm liste ve kartların bulunduğu kartlara ihtiyacım var. Ben bu sorguyu kullanın:

WITH full_lists AS (
    SELECT l.*, 
     COALESCE (json_agg(c) FILTER (WHERE c.id IS NOT NULL), '[]') AS cards 
    FROM lists AS l 
    LEFT JOIN lists_cards ON (l.id = list_id) 
    LEFT JOIN cards AS c ON (c.id = card_id) 
    GROUP BY l.id 
) 
SELECT b.*, 
    COALESCE (json_agg(l) FILTER (WHERE l.id IS NOT NULL), '[]') AS lists 
FROM boards AS b 
LEFT JOIN boards_lists ON (b.id = board_id) 
LEFT JOIN full_lists as l ON (l.id = list_id) 
GROUP BY b.id 

Düzgün çalışır, ama ben panoları ve listeleri almak için iki benzer SEÇ sorularınız ek olarak o, çok hantal olduğunu düşünüyorum. Nasıl basitleştirebilirim?

+0

Neden DB'ın tarafında bu mantık gerçekleştirmek gerekiyor? Filtreleme yapmıyorsunuz. Tüm verileri uygulamaya yükleyip orada işleyemiyor musunuz? JSON (genellikle ham verilerden daha ağır olan) göndermeyeceğiniz için kod/bakım ve daha verimli olması daha kolay olacaktır. – freakish

+0

Bu eylemin DB tarafında yapılması gerektiğini düşündüm. Yani, 3 sorgu (her bir varlık için) yapmak ve uygulamadaki verileri birleştirmek daha basit olurdu. – 1ven

+0

Her şeyden önce: Hiçbir şey yapmaya zorlanmıyorsunuz. :) Ama evet, bu yaklaşım kesinlikle daha basit, genişletmek ve sürdürmek için daha kolay olacaktır. Aynı zamanda daha verimli olabilir, ancak bunu ölçmek zorunda kalacaksınız. Bu sadece bir öneri. Sql ile çalışmak hemen hemen her zaman daha zor ve uygulama gerektirmez, performans talep etmediği sürece IMHO kaçınılmalıdır. – freakish

cevap

İlgili konular