2017-05-29 69 views
0

我想驗證一個postgres json字段,使json中的數組中的每個項目都包含某些屬性。例如,假設我有一個json字段,其中包含一個對象數組contacts,我希望contacts中的每個對象始終具有namephone屬性。像以下各項Postgresql json字段數組項目驗證

{ 
    "contacts": [ 
     { "name": "a", "phone": "123" }, 
     { "name": "b", "phone": "456" } 
    ] 
} 

是否有驗證此,使這種格式始終保持在插入一個內建的方法/更新?

+1

如果你有這樣一個定義的結構,那你爲什麼不規範的數據模型? –

+0

@a_horse_with_no_name這只是一個例子。我用例中的文檔不是嚴格的結構。規範化是可能的,但它需要2-3個與它相關的實體的中間表(我當前的數據庫使用這種形式,但我認爲查詢當前形式需要多次連接,所以json可能更適合)。 – shawon191

回答

1

如果json文檔具有剛性結構,最好將這些數據保存在常規表格中。我認爲這些對象包含許多鍵,包括一些必需的鍵。

以下函數檢查json數組(第一個參數)中的每個對象是否包含所有數組字符串作爲頂級密鑰(第二個參數)。

create or replace function jsonb_has_keys(jsonb, text[]) 
returns boolean language sql as $$ 
    select bool_and(value ?& $2) 
    from jsonb_array_elements($1) 
$$; 

使用功能的檢查約束,例如:

create table test(
    data jsonb check (jsonb_has_keys(data->'contacts', array['name', 'phone'])) 
); 

insert into test values 
('{ 
    "contacts": [ 
     { "name": "a", "phone": "123" }, 
     { "name": "b", "tel": "456" } 
    ] 
}'::jsonb); 

ERROR: new row for relation "test" violates check constraint "test_data_check" 
DETAIL: Failing row contains ({"contacts": [{"name": "a", "phone": "123"}, {"tel": "456", "nam...). 
+0

雖然不是很嚴格,但我想保留的json文檔需要3個相關實體的2箇中間表,並且這個數字在將來很可能會增加。文檔通常會作爲一個整體插入和訪問,並且在大多數情況下插入後不會更新。所以我想將它存儲爲一個json文檔對於開發和性能都更好。如果我錯了,請糾正我。 – shawon191

+0

有了這些假設,你的方法似乎是合理的。 – klin