6 JSONコレクション

JSONコレクションは、一連のJSON文書を格納または提供するデータベース・オブジェクトです。クライアント・アプリケーションは通常、ドキュメントAPIによって提供される操作を使用して、コレクションとその文書を操作します。SQLを使用して操作することもできます。

Oracle Databaseでは、JSONコレクションは、DATAという名前の単一のJSON型のオブジェクト列にJSON文書を提供する特別な表またはビューです。

JSONコレクションのまたはJSONリレーショナル二面性ビュー内の各ドキュメントには、最上位に値がコレクションに対して一意であるdocument-identifierフィールド_idが必要です。脚注1 コレクションにすでに存在するドキュメントと同じ_id値を持つドキュメントを挿入しようとすると、エラーが発生します。

コレクションの_idフィールドがないドキュメントを挿入すると、高速参照用に索引付けられた一意の値とともに自動的に追加されます。二面性ビュー・コレクションに挿入するドキュメントには、_idフィールドを明示的に含める必要があります。

二面性ビュー・コレクションには、_idドキュメント識別子フィールドは必要ありませんが、ある場合は、コレクション全体でその値が一意であることを確認する必要があります

ドキュメントAPIでは通常、挿入する文書に_idドキュメント識別子フィールドが含まれますが、SQLを使用した列DATAへの"サイドバンド"挿入では含まれないことがあります。

_idは、特定のコレクション全体で一意である必要があります。異なるコレクションには、_id値が同じであるドキュメントを含めることができます。この機能の用途の1つは、関連コレクションが関連情報を参照することです。たとえば、customer_profileコレクションとcustomer_complaintsコレクションは、同じ_id値を使用して、実質的に同じ顧客を参照できます。

ドキュメント識別子の値はコレクション全体で一意であるため、ドキュメントAPIではそれを使用してドキュメントに直接アクセスできます。これがドキュメント識別子の目的です。(非二面性) JSONコレクション・ビューにドキュメント識別子フィールドがない場合でも、ドキュメントAPIはコレクション内のドキュメントを読み取ることができますが、問合せ式の検索操作のみを使用します。

SQLファンクションjson_idを使用して、指定するドキュメント識別子フィールドの値を作成できます。json_idによって返される値は、SQL型RAWの識別子であり、実質的にグローバルに一意です。必要なSQL文字列引数によって、RAW値の種類が決まります。文字列'OID'では、12バイトのRAW値が返されます。文字列'UUID'では、16バイトのRAW値が返されます。

フィールド_idがOracleによって自動的に作成される場合、その値は引数'OID'を指定してjson_idを起動することで提供されます。返される12バイトのRAW OID値は、フィールド_idJSON型の値に対応します。OID (オブジェクト識別子)形式は、Oracle Database API for MongoDBと互換性があります。(UUIDの形式は、IETFのUniversally Unique IDentifiers (UUIDs)で提案された標準RFC 9562を順守しています。)

JSONコレクション表または二面性ビューにドキュメントを挿入する場合、型JSONのインスタンスとして値を返すRETURNING句を指定したSQL INSERTコマンドを使用して、その_idフィールドの値を取得できます。これは、フィールドが自動的に追加される場合に便利です。

たとえば、次のPL/SQLコードは、JSON型変数idの値を、自動的に指定されたフィールド_idの値に設定します:

DECLARE id JSON;
BEGIN
  INSERT INTO my_collection mc
    VALUES (JSON('{"a" : 42}'))
    RETURNING mc.data."_id" INTO id;
  DBMS_OUTPUT.put_line(json_serialize(id));
END

このJavaコードでは同じことをしています — JSON型の変数idの値に、自動的に指定されたフィールド_idの値を設定します:

String sql = "INSERT INTO my_collection mc " +
             "VALUES ('{\"a\" : 42}') " +
             "RETURNING mc.data.\"_id\" INTO ?";
OraclePreparedStatement ocstmt = (OraclePreparedStatement) conn.prepareStatement(sql);
ocstmt.registerReturnParameter(1, OracleTypes.JSON);
ocstmt.executeUpdate();
rs = ocstmt.getReturnResultSet();
System.out.println("Retrieved _id : " + rs.getObject(1, OracleJsonBinary.class));

JSONコレクションは実際には特定の種類のデータベース表またはビューですが、ドキュメント中心のクライアント・アプリケーションでは表、ビューまたは列を気にしません。Oracle DatabaseドキュメントAPI (Oracle Database API for MongoDBおよびSimple Oracle Document Access (SODA))によって提供される操作を使用して、コレクションおよび文書のみを考慮します。各APIには、独自の文書およびコレクション操作があります。

JSONコレクション表には、JSON文書が格納されます。このようなコレクションは、CREATE JSON COLLECTION TABLEを使用して作成します。(例6-2を参照してください。)

JSONコレクション・ビューは、JSON文書を基礎となるリレーショナル・データにマップします。次の2種類があります:

  • JSONリレーショナル二面性ビューは、直接更新可能にできます脚注2。つまり、文書(または文書の一部)を、問い合せるのみでなく、直接挿入、更新および削除できます。

    二面性ビューでサポートされる文書には、常にドキュメント識別子フィールド_idがあります。

    このようなコレクションは、CREATE JSON RELATIONAL DUALITY VIEWを使用して作成します。(「二面性ビューの作成」を参照してください。)

  • 非二面性JSONコレクション・ビューは、直接(つまり、文書を使用する)は更新できません。ドキュメントAPIを使用して、文書を問合せすることしかできません。

    このようなコレクションは、CREATE JSON COLLECTION VIEWを使用して作成します。(例6-3を参照してください。)

二面性ビューと非二面性ビューのどちらも、ビューの基にある表データを更新することで、サポートされている文書を間接的に更新できます。それらの相違点は、非二面性ビューが直接的に文書更新可能でないことです。

ヒント:

読取り専用コレクション・ビューのみが必要な場合でも、一般的に、非二面性ビューよりも二面性ビューを使用することをお薦めします。これは、二面性ビューの方が問合せ最適化のパフォーマンスが高いためです。

便宜上、JSONコレクション(表、ビューまたは二面性ビュー)を作成するたびに、指定したコレクション名に対してシノニムが自動的に作成されます。指定した名前が引用符で囲まれていない場合、シノニムは同じ名前ですが引用符で囲まれます。指定した名前が引用符で囲まれている場合、シノニムは同じ名前ですが引用符で囲まれません。引用符で囲まれた名前に、引用符で囲まれていない名前で許可されていない文字が1つ以上含まれている場合、シノニムは作成されません。シノニムを作成すると、コレクションの名前は、引用符で囲まれているかどうかに関係なく、実質的に常に大文字と小文字が区別されるようになります。『Oracle Database SQL言語リファレンス』「CREATE SYNONYM」を参照してください。

二面性ビューでは、SQL/JSON生成関数を使用して、サポートされているJSON文書と、その生成に使用される基礎となるリレーショナル・データとの間のマッピングを定義します。非二面性コレクション・ビューでも生成関数を使用できますが、一般的には(単一の)JSONオブジェクトを返すかぎり、リレーショナル・データに対して任意のSQL問合せを使用できます。

JSON二面性ビューおよびJSONコレクション表は、JSONデータ(二面性ビューの場合は生成され、コレクション表の場合は格納される)に関しては互換性があります。SQL*Plus describeコマンドが示すように、それぞれにDATAという名前の単一のJSON型のオブジェクト列があり、最上位レベルにドキュメント識別子フィールド_idがあります。

関連項目:

『JSONリレーショナル二面性開発者ガイド』「JSONリレーショナル二面性ビューの概要」

JSONコレクションは固定形状(行ごとに1つのJSON文書(オブジェクト)を持つ単一のJSON型オブジェクト列(DATA))であるため、ドキュメントAPIは、表、列または行を気にすることなく、文書に直接アクセスおよび操作できます。

CREATE JSON COLLECTION TABLEおよびCREATE JSON COLLECTION VIEWは、CREATE TABLEおよびCREATE VIEWの基礎となる使用を簡素化するマクロと考えることができます。CREATE JSON COLLECTION TABLEでは、CREATE TABLEと同じオプションのほとんどを使用できます。(例10-1に、PARTITION BY RANGE句の使用例を示します)。

最終的には「単なる表」であるため、通常の表を使用するほとんどの方法でJSONコレクション表を使用できます。特に、GoldenGateを使用して、Oracle DatabaseとMongoDBなどのJSONドキュメント・データベース間など、データベース間でコレクション表をレプリケートできます。(GoldenGateを使用して二面性ビューをレプリケートすることもできます。)

JSONコレクション表には、ETAGサポートという追加オプションがあります。キーワードWITH ETAGとともにCREATE JSON COLLECTION TABLEを指定した場合、各JSON文書にはドキュメント処理フィールド_metadataが含まれ、その値は唯一のフィールドとしてetagを持つオブジェクトです。これは、JSON二面性ビューの場合と同じです。詳細は、「カーレースの例、二面性ビュー」を参照してください。(キーワードWITH ETAGを使用しない場合、_metadataフィールドはありません。)

フィールドetagの値は、文書が書き込まれるたびに更新されるため、文書がデータベースから最後に読み取られてから変更されたかどうかを確認するために使用できます。この動作を使用して、オプティミスティックな同時実行性を実装できます。「二面性ビューでのオプティミスティックな同時実行性制御の使用」を参照してください。

JSONコレクション表を作成するときに、その表に対して1つ以上の式列を定義することもできます。これらの列は仮想列です。値は列に格納されず、列にアクセスするたびにSQL問合せ式を評価した結果として算出されます。式列はデフォルトでは非表示です。

DATAまたはユーザー定義の式列に対して制約を指定することもできます(例6-1を参照)。式列の最も重要な用途は、JSONフィールド値に基づいてコレクションをパーティション化することです(例10-1を参照)。

例6-1 仮想列および制約を使用したJSONコレクション表の作成

この例では、JSONコレクション表employeeを作成します。JSON型の列DATAに加えて、表には非表示の仮想列SALARYが含まれます。この列の値は、最上位レベルのJSONフィールドsalaryの値で、SQL数値です。json_value式は、項目メソッドnumber()を使用してフィールド値をSQL数値として解釈して、フィールド値を抽出します。

仮想列SALARYの値は、ゼロより大きい値に制約され、これにより、列DATAのフィールドsalaryの値も制約されます。

CREATE JSON COLLECTION TABLE employee
  (salary AS (json_value(DATA, '$.salary.number()')),
   CONSTRAINT sal_chk CHECK (salary > 0));

ALTER TABLEを使用して、JSONコレクション表を変更(名前の変更、制約の追加/削除、ユーザー定義の仮想列の追加/削除、パーティション化の追加/削除など)できます。

様々な静的ディクショナリ・ビューを参照して、JSONコレクション表およびビューに関する情報を取得できます。

  • *_JSON_COLLECTIONS — すべてのコレクション表、コレクション・ビューおよびJSONリレーショナル二面性ビューをリストします: 所有者、名前および型(コレクション表、非二面性コレクション・ビューまたは二面性ビュー)。

  • *_JSON_COLLECTION_TABLES — すべてのコレクション表をリストします: 所有者、名前および文書にETAGメタデータ値が含まれているかどうか。

  • *_JSON_COLLECTION_VIEWS — すべてのコレクション・ビュー(所有者と名前)をリストします。

さらに:

  • 表(*_TABLES)およびビュー(*_VIEWS)のディクショナリ・ビューも、コレクション表およびコレクション・ビューをリストします。

  • データベース・オブジェクト(*_OBJECTS)のディクショナリ・ビューも、コレクション表およびコレクション・ビュー(列OBJECT_TYPEがそれぞれTABLEおよびVIEW)をリストします。

関連項目:

例6-2 JSONコレクション表の作成

この例では、コレクション表j_purchaseorderを作成します。DATAという名前の単一のJSON型のオブジェクト列があります。

CREATE JSON COLLECTION TABLE j_purchaseorder;

この例を、例4-1 (2つのリレーショナル列iddate_loaded、およびJSON型の列dataがある、通常の表を作成する)と対比してください。

CREATE JSON COLLECTION TABLEの詳細は、『Oracle Database SQL言語リファレンス』JSON記憶域句に関する項を参照してください

例6-3 (非二面性) JSONコレクション・ビューの作成

この例では、表hr.employeesのリレーショナル・データから非二面性、読取り専用コレクション・ビューempviewを作成します。

CREATE JSON COLLECTION VIEW empview AS
  SELECT JSON {'_id'         : employee_id,
               last_name,             
               'contactInfo' : {email, phone_number},
               hire_date,
               salary}
    FROM hr.employees;

データは、列employee_idlast_nameemailphone_numberhire_dateおよびsalaryから選択されます。結果のJSONドキュメントは、フィールド_idLAST_NAMEcontactInfoHIRE_DATEおよびSALARYを持つオブジェクトです。フィールドcontactInfoの値は、フィールドEMAILおよびPHONE_NUMBERを持つオブジェクトで、その値は列emailおよびphone_numberから取得されます。

CREATE JSON COLLECTION VIEWCREATE VIEWのみに置き換えた場合、結果は同じデータを持つ単一のDATA列を持つ、通常の読取り専用ビューになります。コレクション・ビューにはなりません。Oracle Database API for MongoDBSimple Oracle Document Access (SODA)などのドキュメントAPIを使用して直接問い合せることはできません。

CREATE JSON COLLECTION VIEWの詳細は、『Oracle Database SQL言語リファレンス』CREATE VIEWに関する項を参照してください



脚注の凡例

脚注1: ドキュメント識別子は、ドキュメント・キーと呼ばれることもあります。
脚注2: 二面性ビューを作成するときに、それに対して許可する更新の種類を指定できます。それをしない場合は、デフォルトでそれが読取り専用になります。