2012-11-28 36 views
11

我在數據庫(postgres 9.2.1)中有一個帶有json blob的文本字段。它看起來在一行除了所有與此類似,顯然:將元素添加到Postgres中的JSON對象

{ 
    "keyword": { 
    "checked": "1", 
    "label": "Keyword" 
    }, 
    "agency_name": { 
    "checked": "0", 
    "label": "Agency Name" 
    } 
} 

我需要的元素添加到JSON數組,這樣它看起來像這樣:

{ 
    "keyword": { 
    "checked": "1", 
    "label": "Keyword" 
    }, 
    "something_new": { 
    "checked": "1", 
    "label": "Something New" 
    }, 
    "agency_name": { 
    "checked": "0", 
    "label": "Agency Name" 
    } 
} 

我不像關心新數組元素的位置。它可能在agency_name之後。在postgres中有沒有簡單的方法來做到這一點?

+1

嘗試閱讀http://stackoverflow.com/questions/10560394/how-doi-i -query-using-fields-inside-the-new-postgresql-json-datatype。它可能會幫助你。 –

+0

可能屬於數據庫管理員組 –

回答

5

PostgreSQL還沒有太多的JSON支持功能:我所看到的只有array_to_json,如果有相應的方法將原始JSON轉換爲數組,那麼這可能很有用,您可以在轉換回JSON之前操作添加該附加元素。

可能最好的辦法是使用PL語言來操縱JSON。一個明顯的例子是PLV8,它在PostgreSQL中提供了JavaScript編程功能。你會使用JavaScript編寫一個用戶定義的函數,它會操縱相應的JSON斑點:

當然,許多其他PL語言如Java,Python或Perl的可能只是在爲好使用JSON數據,並且可能更容易在您的系統上安裝。如果您設置了用戶定義的函數,則可以在這些函數中編寫這些函數。

+2

很明顯不是我想要的答案,但是都很好。謝謝。 – thepriebe

1

版本9.5提供了jsonb_set函數,其中create_missing = TRUE。 在任何其他情況下,使用下面的技巧的附加信息:

SELECT (trim(trailing '}' from data::text) || ', "c":2}')::json 

要添加/使用更換新的價值比較正確的做法:

UPDATE t 
SET data=t3.data 

FROM t AS t1 
INNER JOIN 
(
    SELECT id, json_object_agg(t.k,t.v) 
    FROM 
    (
     SELECT * 
     FROM (SELECT id, json_object_keys(data) as k, data->json_object_keys(data) as v FROM t) as t2 
     WHERE t.k != 'c' 

     UNION ALL 
     SELECT id, 'c'::text as k, '"new value"'::json as v FROM t1 
    ) as t3 
    GROUP by id 
) as t4 ON (t1.id=t4.id) 

要刪除鍵:

UPDATE t 
SET data=t3.data 

FROM t AS t1 
INNER JOIN 
(
    SELECT id, json_object_agg(t.k,t.v) 
    FROM (SELECT id, json_object_keys(data) as k, data->json_object_keys(data) as v FROM t) as t2 
    WHERE t.k != 'c' 
    GROUP by id 
) as t4 ON (t1.id=t4.id) 
+0

感謝您的回答。兩年前PostgreSQL 9.5沒有提供給我。從那以後,我們開始使用postgres提供的JSON數據類型,並使用PHP進行編碼/解碼。當JSON僅僅是數據庫中的一個字符串時,它使事情變得更加困難。 – thepriebe

5

如果升級到PG9.5.1,那麼你可以用sql操作||來合併jsonb,例子

select '{"a":1}'::jsonb || '{"a":2, "b":2}'::jsonb 

將返回{"a": 2, "b": 2}

如果您不能升級到pg9.5.1,恕我直言,這樣做在你的代碼的工作將是一個更好的選擇。您可以將舊的jsonb字符串解析爲映射,然後更新映射,然後轉換爲字符串並更新db-record。

1

我有這個問題。這個解決方案相當「純粹」的對象操作,我喜歡'sql'函數plpgsql。最主要的是分列使用json_each - 給你一個紀錄 - 然後創建一個從

CREATE OR REPLACE FUNCTION json_extend_object(
    input_object json, 
    append_key text, 
    append_object json) 
    RETURNS json AS 
$BODY$ 
    select json_object_agg (((json_val)::record).key, ((json_val)::record).value) 
    from (
     select json_val 
     from (select json_each (input_object) as json_val) disaggr 
     where ((json_val::record).key != append_key) 
     union 
     select newvals 
     from (
      select append_key, append_object 
     ) newvals 
    ) to_rows; 
$BODY$ 
    LANGUAGE sql IMMUTABLE 
    ; 
+0

如何添加到文檔的開頭? – igilfanov

+0

將'newvals'子查詢和UNION放在'to_rows'子查詢的'select json_val'分支之前,而不是之後。 –

5

記錄,即使我有同樣的問題,我想動態添加新的元素,jsonb []。

假定column_jsonb [] = [{ 「名稱」: 「XYZ」, 「年齡」: 「12」}]

UPDATE table_name 
    SET column_jsonb[] = array_append(column_jsonb[],'{"name":"abc","age":"22"}'); 

結果:[{ 「名稱」: 「XYZ」 ,「age」:「12」},{「name」:「abc」,「age」:「22」}]