2017-05-29 9 views
0

json内の配列内のすべての項目に特定のプロパティが含まれるように、postgres jsonフィールドを検証したいと考えています。たとえば、オブジェクトの配列contactsを含むjsonフィールドがあるとします。それぞれのオブジェクトの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配列(第1引数)内の各オブジェクトに、すべての配列文字列が最上位キー(第2引数)として含まれているかどうかをチェックします。

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

関連する問題