8.2 JSONフレックス列からドキュメントへのフィールドのマージ

二面性ビューのフレックス列では、フィールドが事前定義されていないJSONオブジェクトが格納されます(基になる表内)。それらは、基になる特定の列に個別にマップされません。挿入または更新したドキュメント内のオブジェクトの認識されていないフィールドは、そのオブジェクトの、基になる表のフレックス列に自動的に追加されます。

したがって、二面性ビューを再定義せずに、二面性ビューによって生成されたドキュメント・オブジェクトに、そのオブジェクトの基になるフレックス列により、フィールドを追加できます。これにより、二面性ビュー、およびそれでサポートされているドキュメントに対して、別の種類のスキーマ柔軟性が提供されます。指定された基になる表に、フレックスとしてそのビュー内で識別された列がない場合、新しいフィールドは、その表によって生成されたオブジェクトに自動的には追加されません。このような柔軟性が必要な場合はフレックス列を追加します。

なお、のフレックス列という呼び方は技術的には正しくありません。フレックス列は、フレックスとして指定されている二面性ビュー列です(そのビューの場合にフレックス)。

personにリレーショナル列が3つとJSON型列extrasがあり、それらの値がJSONオブジェクトである必要がある場合を考えてみます。


CREATE TABLE person (
  pid    NUMBER PRIMARY KEY,
  first  VARCHAR2(20),
  last   VARCHAR2(20),
  extras JSON (OBJECT));

二面性ビューperson_merge_dvでは、列extras除くpersonの各列がドキュメント・フィールドにマップされています。列extrasがフレックス列として宣言されています。GraphQLおよびSQLでのビュー定義を次に示します:脚注1

GraphQL:

CREATE JSON DUALITY VIEW person_merge_dv AS 
  person @update @insert @delete
    {_id       : pid,
     firstName : first,
     lastName  : last,
     extras @flex};

SQL:

CREATE JSON RELATIONAL DUALITY VIEW person_merge_dv AS
  SELECT JSON {'_id'       : p.pid,
               'firstName' : p.first,
               'lastName'  : p.last,
               p.extras AS FLEX COLUMN}
    FROM person p WITH UPDATE INSERT DELETE;

ビューperson_merge_dvにドキュメントを挿入すると、表personによって生成されたオブジェクトでは認識されないフィールド(この場合はフィールドnickName)が、フレックス列person.extrasに追加されます。表personによって生成されたオブジェクトは、ドキュメントの最上位オブジェクトです。フィールドnickNameは、そのオブジェクトに追加されます。

INSERT INTO person_merge_dv VALUES ('{"_id"       : 2,
                                      "firstName" : "John",
                                      "nickName"  : "Anon Y",
                                      "lastName"  : "Doe"}');

挿入されたドキュメントを選択すると、フレックス列のオブジェクトに格納されたフィールド、および他の列に明示的にマップされたフィールドが同じオブジェクト内に存在することがわかります。フィールドnickNameは、フレックス列内のオブジェクトから、フレックス列の表personによって生成されたオブジェクトにマージされました。

SELECT pdv.data FROM person_merge_dv pdv
           WHERE pdv.data."_id" = 2;
{"_id":2,"firstName":"John","lastName":"Doe","nickName":"Anon Y"}

personを問い合せると、フィールドnickNameが、フレックス列extrasに格納されているJSONオブジェクトに含まれていることがわかります。(ここではビューperson_merge_dvへのドキュメント挿入の前に表personが空であると想定していますが、次を参照してください。)

SELECT p.* FROM person p;
PID FIRST  LAST EXTRAS
--- -----  ---- ------
  2 John   Doe  {"nickName":"Anon Y"}

person.extras別の二面性ビューと共有されている場合はその内容に対する変更は両方のビューに反映されることに注意してください。このことが必要な場合もそうでない場合もあります。このことに留意してください。

たとえば、表personはここでは「JSON列からドキュメントへの値の埋込み」においてと同様に定義されています。「JSON列からドキュメントへの値の埋込み」でオブジェクト{"middleName":"X", "nickName":"Anon X"}が同じ列person.extrasに挿入されると考えると、その挿入に加えて二面性ビューperson_merge_dvへの前述の挿入が実行された結果、両方のオブジェクトがその表に存在することになります。

SELECT p.* FROM person p;
PID FIRST  LAST EXTRAS
--- -----  ---- ------
  1 Jane   Doe  {"middleName":"X","nickName":"Anon X"}

  2 John   Doe  {"nickName":"Anon Y"}

どちらの二面性ビューでもJane DoeとJohn Doeのデータが使用されますが、列extras内のオブジェクトは別々の方法で使用されます。ビューperson_embed_dvでは、それらがフィールドmoreInfoの値として埋め込まれます。ビューperson_merge_dvでは、それらのフィールドが最上位でマージされます。

SELECT pdv.data FROM person_embed_dv pdv;
{"_id":1,"firstName":"Jane","lastName":"Doe",
 "moreInfo":{"middleName":"X","nickName":"Anon X"}}
{"_id":2,"firstName":"John","lastName":"Doe",
 "moreInfo":{"nickName":"Anon Y"}}
SELECT pdv.data FROM person_merge_dv pdv;
{"_id":1,"firstName":"Jane","lastName":"Doe",
 "middleName":"X","nickName":"Anon X"}
{"_id":2,"firstName":"John","lastName":"Doe",
 "nickName":"Anon Y"}

別々のビューで、同じ情報を別々の形式で存在させることができます。これは、二面性ビューにも、非二面性ビューにも当てはまります。

ノート:

表内のフレックス列は単なる二面性ビュー構成メンバーです。その表自体では、"フレックス列"の意味も動作もありません。同じ表に、様々な二面性ビュー内のフレックス列として、または同じ二面性ビュー内の様々な場所にあるフレックス列として使用される、様々な列を含めることができます。本当にその列の内容をそこで共有する必要がある場合を除き、1つの列(すべての型)を様々な場所で共有しないでください。



脚注一覧

脚注1: これは、「JSON列からのドキュメントへの値の埋込み」での二面性ビュー定義とは異なります。つまり、(1)列extrasはフレックス列としてラベル付けされており、(2)それはフィールドにマップされません。