2012-08-09 26 views
3

我在postgres數據庫中有以下記錄。 parent_pk與父子關係中的pk相關。Postgres/JSON - 將父子關係轉換爲json

 
pk    name    type   parent_pk 
---   ----    ----   --------- 
1    hnumber101  house   0 
2    hnumber201  house   0 
101   dodge_charger vehicle   1 
102   mustang   vehicle   1 
103   civic   vehicle   2 
301   john    user   101 
302   edward   user   102 
303   john    user   102 
304   john    user   103 

And I want to generate a json out of the above in the following format- 

[ { 
    "id": 1, 
    "name": "hnumber101", 
    "type": "house" 
    "child": [ { 
       "id": 101, 
       "name": "dodge charger", 
       "type": "vehicle" 
       "child": [{ 
         "id": 301, 
         "name": "john", 
         "type": "user" 
         }],        
       }, 
       { 
       "id": 102, 
       "name": "mustang", 
       "type": "vehicle" 
       "child": [{ 
         "id": 303, 
         "name": "john", 
         "type": "user" 
         }, 
         { 
         "id": 302, 
         "name": "edward", 
         "type": "user" 
         }],        
       }], 
    }, 
{ 
    "id": 2, 
    "name": "hnumber201", 
    "type": "house" 
    "child": [ { 
       "id": 103, 
       "name": "civic", 
       "type": "vehicle" 
       "child": [{ 
         "id": 304, 
         "name": "john", 
         "type": "user" 
         }], 

       }], 
    }] 

我一直在使用WITH遞歸查詢的嘗試,但得到的條目列表,然後我必須做大量的循環周圍的/在我的Java代碼中的哈希映射來獲取父裏面那個孩子塊。 什麼是最有效的方法來做到這一點?

+0

9.2中的JSON支持非常有限。 'row_to_json'構造函數不支持匿名行,沒有'scalar_to_json'或'json_escape'將單個值包裝爲JSON,並且沒有聚合或合併/附加函數。這使得建立與行類型不相對應的值非常困難:-( – 2012-08-09 23:35:10

+0

您是否有將JSON文件加載到數據庫表中的代碼,保存ID和parentID? – 2015-12-12 18:16:55

回答

3

這些方針的東西:

SELECT things.pk, things.name, things.type, array_agg(sub.pk) AS children 
FROM things 
LEFT JOIN things sub ON sub.parent_pk = things.pk 
GROUP BY things.pk, things.name, things.type; 
 
pk |  name  | type | children 
-----+---------------+---------+----------- 
    1 | hnumber101 | house | {102,101} 
101 | dodge charger | vehicle | {301} 
102 | mustang  | vehicle | {303,302} 
301 | john   | user | {NULL} 
302 | edward  | user | {NULL} 
303 | john   | user | {NULL} 

收集行成PKMap<Integer, Thing>加密映射。

class Thing { 
    Integer id; 
    String name; 
    String type; 
    Integer[] children; 

    public String printMe(Map<Integer, Thing> allThings) { 
    String ret = "... format json stuff here"; 
    for(Integer childId in children) { 
     Thing child = allThings.get(childId); 
     ret += child.printMe(allThings); 
    } 
    ret += "Format json stuff here"; 
    return ret; 
    } 
}; 
+0

是的,如果您希望它們作爲JSON直接使用你必須爲'CREATE TYPE'創建一個新的行類型,例如'CREATE TYPE blah(id integer,name text,type text,children int [])'',然後將上述查詢包裝在一個SQL函數中,返回SETOF blah'。然後可以從the_function()中選擇row_to_json(x)FROM the_function()AS x'或'SELECT array_to_json(array_agg(x))作爲x''。與XML或hstore支持相比,迂迴迂迴,因爲json沒有任何用處集合或運營商:) – 2012-08-09 23:38:27

+0

這很好,我喜歡查詢,這使事情變得更加簡單,我還有一個問題:是否有可能用父ID填充用戶的'空'子?所以對於用戶來說,孩子是父母名單,這就像查詢汽車約翰駕駛什麼在那個房子裏?試圖想想如果它有可能獲得一個查詢中的所有信息。 – Harpreet 2012-08-10 19:56:11

+0

@jkj:我有類似的要求,我怎麼能在Oracle上面寫SQL。 – JDev 2013-05-07 21:58:01