7 MLE JavaScriptコードでのSODAコレクションの操作
Simple Oracle Document Access (SODA)はNoSQL形式のAPIセットであり、これを使用すると、Oracle Databaseのドキュメント(特にJSON)のコレクションを作成および格納でき、Structured Query Language (SQL)や、ドキュメントがどのようにデータベースに格納されているかを理解していなくても、そのコレクションの取得や問合せを行うことができます。
SODA APIは様々なプログラミング言語用に存在しており、MLE JavaScriptのサポートが含まれています。SODA APIはドキュメント中心です。任意のSODA実装を使用して、ほぼあらゆる種類のドキュメント(ビデオ、イメージ、サウンド、およびその他のバイナリ・コンテンツを含む)について、作成、読取り、更新、削除(CRUD)操作を実行できます。また、任意のSODA実装を使用し、パターン一致: 例による問合せ(QBE)を使用してJavaScript Object Notation (JSON)ドキュメントのコンテンツを問い合せることができます。CRUD操作はドキュメント・キーまたはQBEによって決定できます。
この章では、クライアント側のnode-oracledb
ドライバではなくマルチリンガル・エンジン(MLE)に基づいて、データベースでのJavaScriptについて説明します。この章でJavaScriptについて述べられている場合は常に、暗黙的にMLE JavaScriptを示します。
関連項目:
SODAに関する全体概要は、『Oracle Database Simple Oracle Document Access (SODA)の概要』を参照してください
トピック
- SODA for In-Database JavaScriptの操作の概要
SODA APIは、MLE JavaScript SQLドライバの一部です。コレクションおよびドキュメントの対話においては、SODAデータベース・オブジェクトを取得する前に、まずデータベースとの接続を確立する必要があります。 - SODAオブジェクト
SODA APIで使用されるオブジェクト。 - SODA for In-Database JavaScriptの使用
SODA for In-Database JavaScriptにアクセスする方法と、これを使用してコレクションに対する作成、読取り(取得)、更新および削除(CRUD)操作を実行する方法について説明します。
SODA for In-Database JavaScriptの操作の概要
SODA APIは、MLE JavaScript SQLドライバの一部です。コレクションおよびドキュメントの対話においては、SODAデータベース・オブジェクトを取得する前に、まずデータベースとの接続を確立する必要があります。
SODAデータベースは、SODA APIを操作する場合の最上位の抽象オブジェクトです。
図7-1に、標準制御フローを示します。
クライアント側のNode.jsまたはDenoから移植されていないアプリケーションでは、グローバル・スコープで使用可能な頻繁に使用される多数の変数など、MLE JavaScript SQLドライバで使用可能なコーディング支援のメリットが得られます。使用可能なグローバル変数と型の完全なリストは、「MLE JavaScriptドライバの操作」を参照してください。
SODAアプリケーションの場合、最も重要なグローバル変数は、SodaDatabase
オブジェクトを表すsoda
オブジェクトです。soda
オブジェクトをグローバル・スコープで使用できるため、ボイラープレート・コードを記述する必要性が少なくなります。
SODAオブジェクト
SODA APIで使用されるオブジェクト。
-
SodaDatabase
: SODA操作の最上位オブジェクト。これは、Oracle Database接続から取得されます。SODAデータベースは抽象化されたものであるため、そのSODAデータベース内のSODAコレクションにアクセスでき、そのコレクション内のドキュメントにアクセスできます。SODAデータベースは、Oracle Databaseのユーザーまたはスキーマに似ています。コレクションは表に似ています。ドキュメントは、1つの列に一意のドキュメント・キー、1つの列にドキュメント・コンテンツ、およびその他の列に様々なドキュメント属性を含む表の行に似ています。MLE JavaScript SQLドライバでは、soda
オブジェクトをグローバル変数として使用できます。これはSodaDatabase
オブジェクトを表し、ボイラープレート・コードを記述する必要性が少なくなります。 -
SodaCollection
: SODAドキュメントのコレクションを表します。デフォルトでは、コレクションを使用するとJSONドキュメントを格納でき、各ドキュメントにデフォルトのメタデータ・セットが追加されます。ほとんどのユーザーにはこれをお薦めします。ただし、オプションのメタデータを使用すると、そのデータベース・ストレージ、バージョンおよびタイムスタンプ・ドキュメント・コンポーネントの追跡の有無、それらのコンポーネントの生成方法、サポートされるドキュメント・タイプなど、コレクションに関する様々な詳細を設定できます。 -
SodaDocument
: ドキュメントを表します。通常、ドキュメント・コンテンツはJSONです。ドキュメントには、コンテンツ、キー、タイムスタンプ、メディア・タイプなどのプロパティがあります。デフォルトでは、ドキュメント・キーが自動的に生成されます。
-
SodaDocumentCursor
:find()
操作からのgetCursor()
メソッドの結果を表すカーソル・オブジェクト。反復すると、各SodaDocument
にアクセスできます。 -
SodaOperation
: ドキュメントに対する読取りおよび書込み操作を実行するためにfind()
で使用される内部オブジェクト。つなげられたメソッドにより、SodaOperation
オブジェクトにプロパティが設定されます。これをターミナル・メソッドで使用して、ドキュメントを検索、カウント、置換または削除します。これは、直接アクセスできない内部オブジェクトです。
関連項目:
mle-js-oracledb
でのSODAオブジェクトの使用の詳細は、サーバー側JavaScript APIのドキュメントを参照してください
SODA for In-Database JavaScriptの使用
SODA for In-Database JavaScriptにアクセスする方法と、これを使用してコレクションに対する作成、読取り(取得)、更新および削除(CRUD)操作を実行する方法について説明します。
この項では、SODA for MLE JavaScriptについて説明します。この項のコード・スニペットは、読みやすくするために簡略化されている場合があります。JavaScriptファンクションの全体がリストされるように注意されていますが、単独では実行できません。ファンクション定義をJavaScriptモジュールに埋め込み、MLE JavaScript SQLドライバをインポートすると、これらのコード例がOracle Database 23cの有効なJavaScriptコードに変換されます。
トピック
- SODA for In-Database JavaScriptの開始
SODA for In-Database JavaScriptにアクセスする方法、およびこれを使用してデータベース・コレクションを作成し、ドキュメントをコレクションに挿入し、コレクションからドキュメントを取得する方法について説明します。 - SODA for In-Database JavaScriptによるドキュメント・コレクションの作成
SODA for In-Database JavaScriptを使用して新しいドキュメント・コレクションを作成する方法について説明します。 - SODA for In-Database JavaScriptでの既存のドキュメント・コレクションのオープン
メソッドSodaDatabase.openCollection()
を使用して、既存のドキュメント・コレクションをオープンしたり、指定された名前が既存のコレクションを示しているかどうかをテストできます。 - SODA for In-Database JavaScriptによる特定のコレクションの有無の確認
SodaDatabase.openCollection()
を使用すると、特定のコレクションの存在を確認できます。コレクションの引数が既存のコレクションを示さない場合、null
を返し、それ以外の場合、その名前のコレクションをオープンします。 - SODA for In-Database JavaScriptによる既存のコレクションの検出
SodaDatabase.getCollectionNames()
を使用すると、特定のSodaDatabase
オブジェクトのすべての既存コレクションの名前をフェッチできます。 - SODA for In-Database JavaScriptによるドキュメント・コレクションの削除
SodaCollection.drop()
を使用して、既存のコレクションを削除します。 - SODA for In-Database JavaScriptによるドキュメントの作成
SODA for In-Database JavaScriptによるドキュメントの作成について説明します。 - SODA for In-Database JavaScriptによるコレクションへのドキュメントの挿入
SodaCollection.insertOne()
または関連コール(sodaCollection.insertOneAndGet()
など)を使用すると、ドキュメントをコレクションに追加できます。コレクションがクライアント割当てキーで構成されておらず、入力ドキュメントがキーを指定していない場合、これらのメソッドでは、ドキュメント・キーが自動的に作成されます。 - SODA for In-Database JavaScriptによるコレクションへのドキュメントの保存
SodaCollection.save()
およびsaveAndGet()
を使用して、ドキュメントをコレクションに保存します。 - SODA for In-Database JavaScriptの読取りおよび書込み操作
読取りおよび書込み操作(挿入および保存以外)を指定する主な方法は、SodaOperation
クラスが提供するメソッドを使用することです。SodaOperation
メソッドをつなげて、コレクションに対する読取りおよび書込み操作を指定できます。 - SODA for In-Database JavaScriptによるコレクション内のドキュメントの検索
コレクション内のドキュメントを検索するには、SodaCollection.find()
を呼び出します。SodaOperation
オブジェクトが作成されて戻されます。これは、非ターミナル・メソッドおよびターミナル・メソッドを含むメソッド・チェーンを介して使用されます。 - SODA for In-Database JavaScriptによるコレクション内のドキュメントの置換
コレクション内のあるドキュメントのコンテンツを別のドキュメントのコンテンツで置き換えるには、まずそのキーを使用して、変更するドキュメントを検索します。SodaOperation.key()
は非ターミナル操作であるため、コンテンツを置換する最も簡単な方法は、SodaOperation.key()
をSodaOperation.replaceOne()
またはSodaOperation.replaceOneAndGet()
につなげることです。 - SODA for In-Database JavaScriptによるコレクションからのドキュメントの削除
コレクションからのドキュメントの削除は置換と似ています。最初のステップは、検索操作(通常はドキュメントのキーに基づいて、またはSodaOperation.filter()
の検索式を使用して)を実行することです。SodaOperation.remove()
のコールはターミナル操作です。つまり、チェーンの最後の操作です。 - SODA for In-Database JavaScriptによるコレクション内のドキュメントの索引付け
索引は、NoSQLスタイルのSODA APIとリレーショナル・アプローチのどちらを使用するかに関係なく、データ・アクセスを高速化できます。SODAコレクション内のドキュメントの索引付けには、SodaCollection.createIndex()
を使用します。そのIndexSpec
パラメータはテキストのJSON索引指定です。 - SODA for In-Database JavaScriptを使用したコレクションのデータ・ガイドの取得
データ・ガイドは、一連のJSON文書に含まれる構造および型情報の概要を示します。これらの文書内で使用されているフィールドに関するメタデータを記録します。JSONドキュメントに対する優れたインサイトを提供し、データ・セットの概要把握に役立ちます。 - SODA for In-Database JavaScriptによるトランザクションの処理
クライアント側のJavaScript SQLドライバとは異なり、MLE JavaScript SQLドライバはautoCommit
機能を提供していません。モジュール・コールの場合はPL/SQLレイヤーで、またはconnection.commit()
かconnection.rollback()
をコールすることでJavaScriptコードで直接的に、トランザクションをコミットまたはロールバックする必要があります。 - SODA for In-Database JavaScriptの使用例の概要
SODA for In-Database JavaScriptの使用を最初から最後まで示すエンドツーエンドの例が含まれています。
SODA for In-Database JavaScriptの開始
SODA for In-Database JavaScriptにアクセスする方法、およびこれを使用してデータベース・コレクションを作成し、ドキュメントをコレクションに挿入し、コレクションからドキュメントを取得する方法について説明します。
SODA for MLE JavaScriptの使用を開始する前に、コレクションの格納に使用されるアカウントにSODA_APP
ロールを付与する必要があります:
grant soda_app to soda_user
-
SODAコレクションの作成、
-
JSONドキュメントの挿入、および
-
コレクション内のすべてのSODAドキュメントに対する反復と、画面へのその内容の出力
例7-1で示す各概念(コレクションの作成、ドキュメントの追加と変更、およびコレクションの削除)については、この章の後半で詳しく説明します。
例7-1 MLE JavaScriptでのSODAの一般的なワークフロー
この例では、MLE JavaScriptでSODAコレクションを使用する一般的なワークフローを示します。
CREATE OR REPLACE MLE MODULE intro_soda_mod
LANGUAGE JAVASCRIPT AS
import oracledb from "mle-js-oracledb";
export function testSODA(dropCollection) {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// Create a collection with the name "MyJSONCollection".
// This creates a database table, also named "MyJSONCollection",
// to store the collection. If a collection with the same name
// exists it will be opened
const col = db.createCollection("MyJSONCollection");
// Create a JSON document (based on the HR.EMPLOYEES table for employee 100)
const doc = {
"employee_id": 100,
"job_id": "AD_PRES",
"last_name": "King",
"first_name": "Steven",
"email": "SKING",
"manager_id": null,
"department_id": 90
};
// Insert the document into a collection.
col.insertOne(doc);
// Find all documents in the collection and print them on screen
try {
// use a cursor to iterate over all documents in the collection
const c = col.find().getCursor();
let resultDoc;
while (resultDoc = c.getNext()) {
const content = resultDoc.getContent();
console.log(`
------------------------------------------
key: ${resultDoc.key}
content (select fields):
- employee_id ${content.employee_id}
- job_id ${content.job_id}
- name ${content.first_name} ${content.last_name}
version: ${resultDoc.version}
last modified: ${resultDoc.lastModified}
created on: ${resultDoc.createdOn}
media type: ${resultDoc.mediaType}`
);
}
// it is very important to close the SODADocumentCursor to free resources
c.close();
} catch (err) {
throw err;
}
// commit open transactions
connection.commit();
// optionally drop the collection
if (dropCollection) {
col.drop();
}
}
/
SODA for In-Database JavaScriptによるドキュメント・コレクションの作成
SODA for In-Database JavaScriptを使用して新しいドキュメント・コレクションを作成する方法について説明します。
コレクションを使用すると、ドキュメントを論理的にグループ化できます。コレクションを作成またはコレクションにアクセスする前に、いくつかのステップを完了する必要があります。まず接続オブジェクトを作成します。接続オブジェクトは、MLE JavaScriptモジュールでのすべてのSODA対話の開始点です:
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
接続を取得したら、それを使用してConnection.getSodaDatabase()
をコールでき、これは、コレクションを作成するための前提条件となります:
// get a SODA database
const db = connection.getSodaDatabase();
SODAデータベースが使用できる状態で最後に行うステップは、コレクションの作成です。コレクション名では大/小文字が区別されます:
// Create a collection with the name "MyJSONCollection".
// This creates a database table, also named "MyJSONCollection",
// to store the collection. If a collection with the same name
// exists, it will be opened
const col = db.createCollection("MyJSONCollection");
前述の文は、デフォルトでJSONドキュメントを格納できるコレクションを作成します。SodaDatabase.createCollection()
に渡されているコレクション名が既存のコレクション名である場合、単にそのコレクションがオープンします。また、SodaDatabase.openCollection()
を使用して既存する既知のコレクションをオープンすることもできます。
カスタム・メタデータ(例7-2を参照)がSodaDatabase.createCollection()
に指定されていないかぎり、デフォルトのコレクション・メタデータが提供されます。デフォルトのメタデータには、次の特性があります:
- コレクション内の各ドキュメントには、次のコンポーネントがあります:
- キー
- コンテンツ
- 作成タイムスタンプ
- 最終変更タイムスタンプ
- バージョン
- コレクションはJSONドキュメントのみを格納できます。
- ドキュメント・キーおよびバージョン情報は、汎用一意識別子(UUID)機能を使用して自動的に生成されます。
オプションのコレクション・メタデータをcreateCollection()
のコールに提供できますが、ほとんどの場合、デフォルトのコレクション構成をお薦めします。
すでに同じ名前のコレクションが存在する場合は、単にそのコレクションがオープンし、そのオブジェクトが戻されます。カスタム・メタデータがメソッドに渡され、そのメタデータが既存のコレクションのものと一致しない場合、コレクションはオープンせず、エラーが発生します。一致するには、すべてのメタデータ・フィールドが同じ値である必要があります。
関連項目:
コレクション・メタデータの詳細は、『Oracle Database Simple Oracle Document Access (SODA)の概要』を参照してください。
例7-2 カスタム・メタデータを含むコレクションの作成
この例では、カスタム・メタデータを含むコレクションの作成方法を示します。キーを、VARCHAR2
列に格納される自動作成されたUUID値として格納するのではなく、数値フィールドとして格納します。
export function createCustomCollection() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// create a collection with custom metadata. Unless a custom
// metadata field (keyColumn, versionColumn) is specified it
// will not be used/present in the collection. The metadata
// argument is mostly based on the defaults except for the
// client-assigned key column
const col = db.createCollection(
"myCustomCollection",
{
"metaData": {
"keyColumn": {
"name": "ID",
"sqlType": "NUMBER",
"assignmentMethod": "CLIENT"
},
"versionColumn": {
"name": "VERSION",
"method": "UUID"
},
"lastModifiedColumn": {
"name": "LAST_MODIFIED"
},
"creationTimeColumn": {
"name": "CREATED_ON"
}
}
}
);
console.log(`
Custom collection created.
Assignment method: ${col.metaData.keyColumn.assignmentMethod}`
);
}
値がデフォルトから外れているフィールドはkeyColumn
のみですが、versionColumn
、lastModifiedColumn
およびcreationTimeColumn
を追加する必要があります。そうしないと、コレクション内で使用されません。
SODA for In-Database JavaScriptでの既存のドキュメント・コレクションのオープン
メソッドSodaDatabase.openCollection()
を使用して、既存のドキュメント・コレクションをオープンしたり、指定された名前が既存のコレクションを示しているかどうかをテストできます。
例7-3 既存のドキュメント・コレクションのオープン
この例では、collectionName
という名前のコレクションをオープンします。SodaDatabase.openCollection()
によって戻されるコレクション・オブジェクトがnull
でないことを確認することが非常に重要です。リクエストされたコレクションが存在しない場合、メソッドはエラーをスローするのではなく、null
値を戻します。
export function openCollection(collectionName) {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// perform a lookup. If a connection cannot be found by that
// name no exception nor error are thrown, but the resulting
// collection object will be null
const col = db.openCollection(collectionName);
if (col === null) {
throw `No such collection ${collectionName}`;
}
// do something with the collection
}
SODA for In-Database JavaScriptによる特定のコレクションの有無の確認
SodaDatabase.openCollection()
を使用すると、特定のコレクションの存在を確認できます。コレクションの引数が既存のコレクションを示さない場合、null
を返し、それ以外の場合、その名前のコレクションをオープンします。
例7-3では、collectionName
が既存のコレクションの名前でない場合、col
には値null
が代入されます。
SODA for In-Database JavaScriptによる既存のコレクションの検出
SodaDatabase.getCollectionNames()
を使用すると、特定のSodaDatabase
オブジェクトのすべての既存コレクションの名前をフェッチできます。
コレクションの数が非常に多い場合は、戻される名前の数を制限できます。また、例7-5に示すように、ユーザー定義文字列で始まるコレクションに検索を制限できます。
例7-4 既存のすべてのコレクション名のフェッチ
この例では、メソッドgetCollectionNames()
を使用して既存のすべてのコレクションの名前を出力します。
export function printCollectionNames() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// loop over all collection names
const allCollections = db.getCollectionNames();
for (const col of allCollections) {
console.log(`- ${col}`);
}
}
/
例7-5 戻されるコレクションのリストのフィルタリング
この例では、ユーザー定義文字列startWith
で始まるコレクションの名前のみを出力することによって、getCollectionNames()
の結果を制限します。
export function printSomeCollectionNames(numHits, startWith) {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// loop over all collection names
const allCollections = db.getCollectionNames(
{
limit: numHits,
startsWith: startWith
}
);
for (const col of allCollections) {
console.log(`- ${col}`);
}
}
SODA for In-Database JavaScriptによるドキュメント・コレクションの削除
SodaCollection.drop()
を使用して、既存のコレクションを削除します。
注意:
SQLを使用して、コレクションの基礎になっているデータベース表を削除しないでください。コレクションを削除することは、そのデータベース表を削除することで終わりにはなりません。表に格納されるドキュメント以外にも、コレクションにはOracle Databaseに永続化されるメタデータも含まれています。コレクションの基礎になっている表を削除しても、コレクション・メタデータは削除されません。
ノート:
SODAを使用する通常のアプリケーションを日常的に使用する場合、コレクションをドロップして再作成する必要はありません。しかし、なんらかの理由でこれを行う必要がある場合は、このガイドラインが適用されます。
多少なりともコレクションを使用しているアプリケーションがある場合は、コレクションを削除した後に異なるメタデータで再作成しないでください。すべてのライブSODAオブジェクトが解放されるように、コレクションを再作成する前にこのようなアプリケーションをすべて停止します。
コレクションのドロップだけでは、問題は発生しません。ドロップされたコレクションの読取りまたは書込み操作でエラーが発生します。コレクションをドロップして同じメタデータを持つコレクションを再作成しても、問題はありません。ただし、異なるメタデータでコレクションを再作成して、SODAオブジェクトを使用するライブ・アプリケーションが存在する場合、古いコレクションがアクセスされるというリスクがあり、この場合、エラーは発生しません。
SODA for Javaなど、コレクション・メタデータ・キャッシングを許可するSODA実装では、このようなキャッシュが有効になっている場合に、このリスクが高くなります。その場合、コレクションがドロップされても(共有またはローカルの)キャッシュが古いコレクション・オブジェクトのエントリを返す可能性があります。
ノート:
SodaCollection.drop()
を使用する前に、コレクションへのすべての書込みをコミットしてください。メソッドが正常に終了するには、コレクションに対してコミットされていないすべての書込みを最初にコミットする必要があります。そうでない場合は、例外が発生します。
例7-6 コレクションの削除
この例は、コレクションcol
を削除します。
CREATE OR REPLACE MLE MODULE drop_col_mod
LANGUAGE JAVASCRIPT AS
import oracledb from "mle-js-oracledb";
export function openAndDropCollection(collectionName) {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// look the collection up
const col = db.openCollection(collectionName);
if (col === null) {
throw `No such collection ${collectionName}`;
}
// drop the collection - POTENTIALLY DANGEROUS
col.drop();
}
/
SODA for In-Database JavaScriptによるドキュメントの作成
SODA for In-Database JavaScriptによるドキュメントの作成について説明します。
SodaDocument
クラスはSODAドキュメントを表します。JSONドキュメントが中心ですが、他のコンテンツ・タイプもサポートされています。SodaDocument
には、実際のドキュメントのコンテンツとメタデータの両方が格納されます。
設計上、JavaScriptは特にJSONとの連携に適しているため、これが他のプログラミング言語よりも優位になっています。
次に、単純なJSONドキュメントの例を示します。
// Create a JSON document (based on the HR.EMPLOYEES table for employee 100)
const doc = {
"employee_id": 100,
"job_id": "AD_PRES",
"last_name": "King",
"first_name": "Steven",
"email": "SKING",
"manager_id": null,
"department_id": 90
};
ノート:
SODAでは、JSONコンテンツがRFC 4627に準拠する必要があります。
SodaDocument
オブジェクトは、次の3つの方法で作成できます:
sodaDatabase.createDocument()
の結果として。これは、SODAの挿入および置換メソッドに使用できる元のSodaDocument
オブジェクトです。SodaDocument
には、コンテンツおよびメディア・タイプのコンポーネントが設定されます。createdOn
などの属性は定義されません。SodaDocument.createDocument()
のコール時に指定されていないオプション属性も定義されません。sodaOperation.getOne()
のコールなどのデータベースからの読取り操作、またはsodaOperation.getCursor()
コール後のsodaDocumentCursor.getNext()
からの読取り操作の結果として。これらは、ドキュメントのコンテンツおよび属性(タイムスタンプなど)を含む完全なSodaDocument
オブジェクトを戻します。sodaCollection.insertOneAndGet()
、sodaOperation.replaceOneAndGet()
またはsodaCollection.insertManyAndGet()
メソッドの結果として。これらは、ドキュメント・コンテンツ自体を除くすべての属性を含むSodaDocuments
を戻します。システム生成キーなどのドキュメント属性や、新規および更新されたバージョンのドキュメントを検索する場合に便利です。
ドキュメントには次のコンポーネントがあります。
-
キー
-
コンテンツ
-
作成タイムスタンプ
-
最終変更タイムスタンプ
-
バージョン
-
メディア・タイプ(JSONドキュメントの場合、
"application/json"
)
例7-7 SODAドキュメントの作成
export function createJSONDoc() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// define a payload
const payload = {
"employee_id": 100,
"job_id": "AD_PRES",
"last_name": "King",
"first_name": "Steven",
"email": "SKING",
"manager_id": null,
"department_id": 90
};
// create a SODA document using the default key
const docDefaultKey = db.createDocument(payload);
console.log(`
------------------------------------------
SODA Document using default key
content (select fields):
- employee_id ${docDefaultKey.getContent().employee_id}
- job_id ${docDefaultKey.getContent().job_id}
- first name ${docDefaultKey.getContent().first_name}
media type: ${docDefaultKey.mediaType}`
);
// create a SODA document using a custom key (requires that the
// collection this document is inserted to uses a user-assigned
// key)
const docCustomKey = db.createDocument(
payload,
{
key: "12345"
}
);
// print details about the new SODA Document
console.log(`
------------------------------------------
SODA Document using custom key
content (select fields):
- employee_id ${docCustomKey.getContent().employee_id}
- job_id ${docCustomKey.getContent().job_id}
- first name ${docCustomKey.getContent().first_name}
key: ${docCustomKey.key}
media type: ${docCustomKey.mediaType}`
);
}
この例にあるようなSodaDocument
インスタンスの作成は、標準ではなく例外です。ほとんどの場合、開発者はSodaCollection.insertOne()
またはSodeCollection.insertOneAndGet()
を使用します。SodaCollection.insertOne()
の使用は、例7-8に示されています。
SODA for In-Database JavaScriptによるコレクションへのドキュメントの挿入
SodaCollection.insertOne()
または関連コール(sodaCollection.insertOneAndGet()
など)を使用すると、ドキュメントをコレクションに追加できます。コレクションがクライアント割当てキーで構成されておらず、入力ドキュメントがキーを指定していない場合、これらのメソッドでは、ドキュメント・キーが自動的に作成されます。
SodaCollection.insertOne()
は単にドキュメントをコレクションに挿入しますが、SodaCollection.insertOneAndGet()
はさらに結果ドキュメントを戻します。結果ドキュメントには、ドキュメント・キーおよびその他の生成されたドキュメント・コンポーネントが含まれます。ただし、実際のドキュメントのコンテンツは除きます(これはパフォーマンス向上のために行われます)。
どちらのメソッドでも、カスタム・メタデータを使用してコレクションが作成されていないかぎり、作成タイムスタンプ、最終変更タイムスタンプおよびバージョンの値が自動的に設定されます。カスタム・メタデータには、一部のデフォルト・メタデータが含まれていない場合があります。コレクションで定義されていない属性を問い合せると、NULL値が戻されます。
ノート:
コレクションがクライアント割当てドキュメント・キーで構成されていて(デフォルトの場合と異なるケース)、入力ドキュメントがコレクション内の既存のドキュメントを識別するキーを提供している場合、これらのメソッドは例外をスローします。例外を発生させるのではなく、入力ドキュメントで既存のドキュメントを置き換える場合は、「SODA for In-Database JavaScriptによるコレクションへのドキュメントの保存」を参照してください。
例7-8 コレクションへのSODAドキュメントの挿入
この例では、SodaCollection.insertOne()
を使用してコレクションにドキュメントを挿入する方法を示します。
export function insertOneExample() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// create/open a SODA collection
const col = db.createCollection("MyJSONCollection");
// define a payload
const payload = {
"employee_id": 100,
"first_name": "Steven",
"last_name": "King"
};
// insert the document
col.insertOne(payload);
}
例7-9 コレクションへのドキュメントの配列の挿入
この例では、SodaCollection.insertMany()
を使用して、1つのコマンドで複数のドキュメントを挿入する方法を示します。
export function insertManyExample() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// create/open a SODA collection
const col = db.createCollection("MyJSONCollection");
// define a payload (an array of objects)
const payload = [
{
"employee_id": 100,
"first_name": "Steven",
"last_name": "King"
},
{
"employee_id": 101,
"first_name": "Neena",
"last_name": "Kochhar"
},
{
"employee_id": 102,
"first_name": "Lex",
"last_name": "De Haan"
},
{
"employee_id": 103,
"first_name": "Alexander",
"last_name": "Hunold"
},
{
"employee_id": 104,
"first_name": "Bruce",
"last_name": "Ernst"
},
{
"employee_id": 105,
"first_name": "David",
"last_name": "Austin"
}
]
// insert the document
col.insertMany(payload);
}
SODA for In-Database JavaScriptによるコレクションへのドキュメントの保存
SodaCollection.save()
およびsaveAndGet()
を使用して、ドキュメントをコレクションに保存します。
これらのメソッドは、メソッドinsertOne()
およびinsertOneAndGet()
と似ていますが、コレクションがクライアント割当てドキュメント・キーで構成されていて、入力ドキュメントがコレクション内のドキュメントをすでに識別するキーを提供している場合、入力ドキュメントが既存のドキュメントを置き換える点が異なります。これに対し、メソッドinsertOne()
およびinsertOneAndGet()
は、そのような場合に例外をスローします。
ノート:
デフォルトでは、コレクションは自動的に生成されたドキュメント・キーで構成されます。したがって、デフォルトのコレクションの場合、メソッドsave()
およびsaveAndGet()
は、それぞれメソッドinsertOne()
およびinsertOneAndGet()
と同等です。
例7-10 コレクションへのドキュメントの保存
この例では、SodaCollection.saveAndGet()
の使用方法を示します。JavaScriptコードで、カスタム・メタデータを使用して定義したコレクションにSODAドキュメントを格納し、save()
およびsaveAndGet()
が説明どおりに動作することを確認します。特にキー列はユーザー管理であるため、SodaDocument
コンストラクタでキーが示されています。
CREATE OR REPLACE MLE MODULE save_doc_mod
LANGUAGE JAVASCRIPT AS
import oracledb from "mle-js-oracledb";
export function saveJSONDoc() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// create/open a collection using custom metadata
const col = db.openCollection("myCustomCollection");
if ( col === null ) {
throw `'myCustomCollection' does not exist`;
}
// create the SODA document, use the employee_id as its key
let docCustomKey = db.createDocument(
{
"employee_id": 100,
"job_id": "AD_PRES",
"last_name": "King",
"first_name": "Steven",
"email": "SKING",
"manager_id": null,
"department_id": 90
},
{
"key": "100"
}
);
// insert the document into the custom collection
let savedDoc = col.saveAndGet(docCustomKey);
// get some meta information about the new document
console.log(`Document saved for the 1st time:
- department id: ${docCustomKey.getContent().department_id}
- key: ${savedDoc.key}
- version: ${savedDoc.version}
- last modified: ${savedDoc.lastModified}
- created on: ${savedDoc.createdOn}`);
// correct the previous mistake - the document should have
// been inserted with a department_id of 30
// - create the new document (important to use the same key)
docCustomKey = db.createDocument(
{
"employee_id": 100,
"job_id": "AD_PRES",
"last_name": "King",
"first_name": "Steven",
"email": "SKING",
"manager_id": null,
"department_id": 30
},
{
"key": "100"
}
);
// - update the existing document
savedDoc = col.saveAndGet(docCustomKey);
// - show the changed metadata. Cannot refer to the content
// as it is not returned by saveAndGet() for performance
// reasons
console.log(`Updated document saved successfully:
- department id: ${docCustomKey.getContent().department_id}
- key: ${savedDoc.key}
- version: ${savedDoc.version}
- last modified: ${savedDoc.lastModified}
- created on: ${savedDoc.createdOn}`);
}
/
最初のドキュメントがコレクションに保存された後、ドキュメントのdepartment_id
の値が誤っており、修正が必要なことが判明します。誤りが修正され、ドキュメントが再度保存されます。これにより、前のコンテンツが上書きされ、department_id
が正しい値30
に効率的に設定されます。
SODA for In-Database JavaScriptの読取りおよび書込み操作
読取りおよび書込み操作(挿入および保存以外)を指定する主な方法は、SodaOperation
クラスが提供するメソッドを使用することです。SodaOperation
メソッドをつなげて、コレクションに対する読取りおよび書込み操作を指定できます。
非ターミナルのSodaOperation
メソッドは、呼び出された同じオブジェクトを戻し、メソッドをつなげることができるようにします。
ターミナルのSodaOperation
メソッドは常に、操作を実行するメソッド・チェーンの最後に出現します。
ノート:
SodaOperation
オブジェクトは内部オブジェクトです。そのプロパティは直接変更しないでください。
メソッドのnode-oracledb
ドキュメントに異なる記述がなければ、すべての非ターミナル・メソッドをつなぎ、ターミナル・メソッドでチェーンを終了できます。ただし、すべての組合せに意味があるわけではありません。たとえば、keys()
などのドキュメントを一意に識別しないメソッドとversion()
メソッドをつなげても意味はありません。
表7-1 読取り操作用の非ターミナル・メソッドの概要
メソッド | 説明 |
---|---|
key() |
指定したドキュメント・キーを持つドキュメントを検索します。 |
keys() |
指定した複数のドキュメント・キーを持つ複数のドキュメントを検索します。 |
filter() |
フィルタ仕様(JSONで表される例による問合せ)と一致するドキュメントを検索します。 |
version() |
指定したバージョンのドキュメントを検索します。通常、これはkey() とともに使用されます。
|
headerOnly() |
結果からドキュメント・コンテンツを除外します。 |
skip() |
結果内で指定した数のドキュメントをスキップします。 |
limit() |
結果ドキュメントの数を指定した数に制限します。 |
表7-2 読取り操作用のターミナル・メソッドの概要
メソッド | 説明 |
---|---|
getOne() |
最大1つのドキュメントを戻す操作を作成して実行します。たとえば、非ターミナル・メソッドkey() の呼出しを含む操作などです。
|
getCursor() |
読取り操作の結果によってカーソルを取得します。 |
count() |
操作で見つかったドキュメントの数をカウントします。 |
getDocuments() |
問合せ基準に一致するドキュメントの配列を取得します。 |
表7-3 書込み操作用のターミナル・メソッドの概要
メソッド | 説明 |
---|---|
replaceOne() |
1つのドキュメントを置き換えます。 |
replaceOneAndGet() |
1つのドキュメントを置き換えて、結果ドキュメントを返します。 |
remove() |
ドキュメントをコレクションから削除します。 |
関連項目:
-
SodaOperations
クラスの詳細は、node-oracledbのドキュメントを参照してください。 -
SODAの制限の詳細は、SODAの制限(参考)に関する項を参照してください。
SODA for In-Database JavaScriptによるコレクション内のドキュメントの検索
コレクション内のドキュメントを検索するには、SodaCollection.find()
を呼び出します。SodaOperation
オブジェクトが作成されて戻されます。これは、非ターミナル・メソッドおよびターミナル・メソッドを含むメソッド・チェーンを介して使用されます。
問合せを実行するには、SodaOperation.getCursor()
を呼び出して、その結果のカーソルを取得します。次に、カーソルを使用して結果リスト内の各ドキュメントにアクセスします。これは、例7-1およびその他の例で示されています。リソースを節約するために、カーソルを必ずクローズすることが重要です。
ただし、これはコレクション内のドキュメントを検索する際の一般的なワークフローではありません。SodaOperation
クラスで提供される複数のメソッドをつなげる方が一般的です。
例7-11 キーによるドキュメントの検索
この例は、メソッドfind()
、key()
およびgetOne()
を使用してドキュメントをキーで検索する方法を示しています。
例7-2で示したように、customCollection
が作成されていると想定しています。
CREATE OR REPLACE MLE MODULE find_doc_mod
LANGUAGE JAVASCRIPT AS
import oracledb from "mle-js-oracledb";
export function findDocByKey() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open a collection in preparation of a document
// lookup
const col = db.openCollection("myCustomCollection");
if (col === null) {
throw `myCustomCollection does not exist`;
}
try {
// perform a lookup of a document with key "100"
const doc = col.find().key("100").getOne();
console.log(`
document found for key ${doc.key}
contents: ${doc.getContentAsString()}`
);
} catch (err) {
throw `No document found in 'myCustomCollection' with key 100`;
}
}
/
ノート:
キーは、数値形式の場合でも二重引用符で囲む必要があります。指定されたキーの検索に失敗した場合、データベースはORA-01403 (「データが見つかりません。」)例外をスローします。例外は適切に処理することをお薦めします。この例では、エラーが確実に検出され、業界で最もよく知られている方法に従って処理される責任をファンクションのコール元が担っています。
例7-12 複数のキーを使用したドキュメントの検索
この例では、メソッドfind()
、keys()
、getCursor()
およびgetNext()
を使用して、配列で指定された複数のキーを検索します。
export function findDocByKeys() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open a collection in preparation of a document
// lookup
const col = db.openCollection("myCustomCollection");
if (col === null) {
throw `myCustomCollection does not exist`;
}
try {
// perform a lookup of a document with keys ["100","101"]
const docCursor = col.find().keys(["100", "101"]).getCursor();
let doc
while (( doc = docCursor.getNext())) {
console.log(`
document found for key ${doc.key}
contents: ${doc.getContentAsString()}`
);
}
docCursor.close();
} catch (err) {
throw `No document found in 'myCustomCollection' with either key`;
}
}
ORA-1403 (「データが見つかりません。」という例外)で失敗するのではなく、find()
操作では、単に、コレクションで見つからないキーのデータが戻されません。キーが見つからない場合は、何も戻されません。
例7-13 QBEを使用したコレクション内のドキュメントのフィルタリング
この例では、filter()
を使用してコレクション内のドキュメントを検索します。非ターミナルのSodaOperation.filter()
メソッドは、コレクション内のJSONドキュメントをフィルタする強力な方法を提供し、複雑なドキュメント問合せおよびJSONドキュメントの順序付けを可能にします。フィルタ仕様には、比較、正規表現、論理演算子および空間演算子などを含めることができます。
filterCondition
で定義されている検索式は、部門30
で働く110
より大きい従業員IDを持つすべての従業員に一致します。
export function findDocByFiltering() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open a collection in preparation of a document
// lookup. This particular collection contains all the
// rows from the HR.employees table converted to SODA
// documents
const col = db.openCollection("employees_collection");
if (col === null) {
throw `employees_collection does not exist`;
}
// find all employees with an employee_id > 110 working
// in department 30
const filterCondition = {
"employee_id": { "$gt": 110 },
"department_id": "30"
}
try {
// perform the lookup operation using the QBE
const docCursor = col.find().filter(filterCondition).getCursor();
let doc;
while (( doc = docCursor.getNext())) {
console.log(`
------------------------------------
document found matching the search criteria
- key: ${doc.key}
- employee id: ${doc.getContent().employee_id}
- department ID: ${doc.getContent().department_id}
- name: ${doc.getContent().last_name}`
);
}
docCursor.close();
} catch (err) {
throw `No document found in 'myCustomCollection' with either key`;
}
}
関連項目:
-
SODAフィルタ指定に関する概要は、『Oracle Database Simple Oracle Document Access (SODA)の概要』を参照してください
-
SODAフィルタ指定に関するリファレンス情報は、『Oracle Database Simple Oracle Document Access (SODA)の概要』を参照してください
例7-14 ページ区切り問合せでのskip()およびlimit()の使用
行数が過度に大きくなる場合は、ページ分けするか、戻されるドキュメントの数を制限できます。この例では、このような状況でskip()
およびlimit()
を使用する方法を示します。
export function paginationExample() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open a collection in preparation of a document
// lookup. This particular collection contains all the
// rows from the HR.employees table converted to SODA
// documents
const col = db.openCollection("employees_collection");
if (col === null) {
throw `employees_collection does not exist`;
}
// find all employees with an employee_id > 110 working
// in department 80
const filterCondition = {
"employee_id": { "$gt": 110 },
"department_id": "80"
}
try {
// perform the lookup operation using the QBE, skipping the first
// 10 documents and limiting the result set to 10 documents
const docCursor =
col.find().filter(filterCondition).skip(10).limit(10).getCursor();
let doc
while (( doc = docCursor.getNext())) {
console.log(`
------------------------------------
document found matching the search criteria
- key: ${doc.key}
- employee id: ${doc.getContent().employee_id}`
);
}
docCursor.close();
} catch (err) {
throw `No document found in 'myCustomCollection' with either key`;
}
}
例7-15 ドキュメント・バージョンの指定
この例では、非ターミナル・メソッドversion()
を使用して、特定のドキュメント・バージョンを指定します。これは、書込み操作用のターミナル・メソッドとともに使用する場合、オプティミスティック・ロックの実装に便利です。
export function versioningExample() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open a collection in preparation of a document
// lookup
const col = db.openCollection("myCustomCollection");
if (col === null) {
throw `myCustomCollection does not exist`;
}
try {
// perform a lookup of a document with key "100" and version "v1"
const doc = col.find().key("100").version("v1").getOne();
console.log(`
document found for key ${doc.key}
contents: ${doc.getContentAsString()}`
);
} catch (err) {
throw `No document found for key 100 and version "v1"`;
}
}
例7-16 見つかったドキュメントの数のカウント
この例では、find()
、filter()
およびcount()
メソッドを使用して、コレクションで見つかったドキュメントの数をカウントする方法を示します。filter()
式は、部門30
で働くすべての従業員に結果を制限します。
export function countingExample() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open a collection in preparation of a document lookup
const col = db.openCollection("employees_collection");
if (col === null) {
throw `employees_collection does not exist`;
}
try {
// perform a lookup operation identifying all employees working
// in department 30 limiting the result to headers only
const filterCondition = {"department_id": "30" };
const numDocs = col.find().filter(filterCondition).count();
console.log(`there are ${numDocs} documents matching the filter`);
} catch (err) {
throw `No document found in 'employees_collection' matching the filter`;
}
}
SODA for In-Database JavaScriptによるコレクション内のドキュメントの置換
コレクション内の1つのドキュメントのコンテンツを別のドキュメントのコンテンツで置き換えるには、まずそのキーを使用して、変更するドキュメントを検索します。SodaOperation.key()
は非ターミナル操作であるため、コンテンツを置換する最も簡単な方法は、SodaOperation.key()
をSodaOperation.replaceOne()
またはSodaOperation.replaceOneAndGet()
につなげることです。
SodaOperation.replaceOne()
はドキュメントを置換するのみですが、SodaOperation.replaceOneAndGet()
はドキュメントを置換し、コール元にその結果の新しいドキュメントを提供します。
どちらのメソッドでも、最終変更タイムスタンプとバージョンの値が更新されます。置換では、ドキュメント・キーと作成タイムスタンプは変更されません。
SodaOperation.replace()
とSodaOperation.save()
の違いは、キーがコレクションにまだ存在しない場合、後者では挿入を実行することです。置換操作では、SodaOperation.key()
メソッドによる検索で既存のドキュメントを見つける必要があります。
ノート:
デフォルト・メソッドを含め、バージョンを生成する一部のメソッドでは、ドキュメント・コンテンツのハッシュ値を生成します。このような場合、ドキュメント・コンテンツが変更されないと、バージョンも変更されません。
例7-17 コレクション内のドキュメントの置換および結果ドキュメントの戻し
この例は、コレクション内のドキュメントを置換し、変更されたドキュメントへの参照を戻す方法を示しています。
CREATE OR REPLACE MLE MODULE rep_ret_doc_mod
LANGUAGE JAVASCRIPT AS
import oracledb from "mle-js-oracledb";
export function replaceExample() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open myCustomCollection
const col = db.openCollection("myCustomCollection");
if ( col === null ) {
throw "'myCustomCollection' does not exist";
}
// create the changed SODA document, change department_id to 80
const newDoc = db.createDocument(
{
"employee_id": 100,
"job_id": "AD_PRES",
"last_name": "King",
"first_name": "Steven",
"email": "SKING",
"manager_id": null,
"department_id": 80
}
);;
// perform a lookup of the document about to be changed
try {
const resultDoc = col.find().key("100").replaceOneAndGet(newDoc);
// print some metadata (note that content is not returned for
// performance reasons)
console.log(`Document updated successfully:
- key: ${resultDoc.key}
- version: ${resultDoc.version}
- last modified: ${resultDoc.lastModified}
- created on: ${resultDoc.createdOn}`);
} catch (err) {
throw err;
}
}
/
ノート:
パフォーマンス上の理由から、実際のドキュメントのコンテンツは戻されないため、変更されたコンテンツを読み取ろうとするとエラーが発生します。SODA for In-Database JavaScriptによるコレクションからのドキュメントの削除
コレクションからのドキュメントの削除は置換と似ています。最初のステップは、検索操作(通常はドキュメントのキーに基づいて、またはSodaOperation.filter()
の検索式を使用して)を実行することです。SodaOperation.remove()
のコールはターミナル操作です。つまり、チェーンの最後の操作です。
例7-18 ドキュメント・キーによるコレクションからのドキュメントの削除
この例では、ドキュメント・キーが"100"
のドキュメントを削除します。
CREATE OR REPLACE MLE MODULE rm_doc_mod
LANGUAGE JAVASCRIPT AS
import oracledb from "mle-js-oracledb";
export function removeByKey() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open myCustomCollection
const col = db.openCollection("myCustomCollection");
if ( col === null ) {
throw "'myCustomCollection' does not exist";
}
// perform a lookup of the document about to be removed and
// ultimately remove it.
const result = col.find().key("100").remove();
if ( result.count === 0) {
throw "Document was not deleted - is this an invalid key?"
}
}
/
例7-19 フィルタによるコレクションからのJSONドキュメントの削除
この例では、フィルタを使用して、department_id
が70
のJSONドキュメントを削除します。その後、削除されたドキュメントの数を出力します。
export function removeByFilter() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open employees_collection
const col = db.openCollection("employees_collection");
if ( col === null ) {
throw "'employees_collection' does not exist";
}
// perform a lookup based on a filter expression and remove the
// documents matching the filter
const result = col.find().filter({"department_id": "70"}).remove();
return result.count;
}
SODA for In-Database JavaScriptによるコレクション内のドキュメントの索引付け
索引は、NoSQLスタイルのSODA APIとリレーショナル・アプローチのどちらを使用するかに関係なく、データ・アクセスを高速化できます。SODAコレクション内のドキュメントの索引付けには、SodaCollection.createIndex()
を使用します。そのIndexSpec
パラメータはテキストのJSON索引指定です。
既存の索引は、SodaCollection.dropIndex()
を使用して削除できます。
JSON検索索引は、全文問合せおよび非定型構造問合せに使用され、永続的な記録およびJSONデータ・ガイド情報の自動更新に使用されます。
関連項目:
-
SODA索引の使用の概要については、Oracle Database Simple Oracle Document Access (SODA)の概要を参照
-
SODA索引の仕様に関する情報は、『Oracle Database Simple Oracle Document Access (SODA)の概要』を参照
-
JSON検索索引の詳細は、Oracle Database JSON開発者ガイドを参照
-
JSON検索索引の一部である永続データ・ガイド情報の詳細は、Oracle Database JSON開発者ガイドを参照
例7-20 SODA for In-Database JavaScriptを使用したJSONフィールドに対するBツリー索引の作成
この例では、コレクションemployees_collection
内のJSONドキュメントの数値フィールドdepartment_id
に対して一意ではないBツリー索引を作成します。
CREATE OR REPLACE MLE MODULE b_tree_mod
LANGUAGE JAVASCRIPT AS
import oracledb from "mle-js-oracledb";
export function createBTreeIndex() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open the collection
const col = db.openCollection("employees_collection");
if ( col === null ) {
throw "'employees_collection' does not exist";
}
const indexSpec = {
"name": "departments_idx",
"fields": [
{
"path": "department_id",
"datatype": "number",
"order": "asc"
}
]
};
col.createIndex(indexSpec);
console.log(`B-Tree index successfully created`);
}
/
例7-21 SODA for In-Database JavaScriptを使用したJSON検索索引の作成
この例では、コレクションemployees_collection
のドキュメントを索引付けするためのJSON検索索引の作成方法を示します。これは、非定型問合せおよび全文検索(QBE演算子$contains
を使用する問合せ)に使用できます。これによって、JSONドキュメントに関するデータ・ガイド情報(集計構造情報および型情報)が自動的に蓄積および更新されます。索引仕様には、フィールドname
のみが含まれます(例7-20のBツリー索引とは異なり、フィールドfieldsは含まれません)。
export function createSearchIndex() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open the collection
const col = db.openCollection("employees_collection");
if ( col === null ) {
throw "'employees_collection' does not exist";
}
const indexSpec = {
"name": "SEARCH_AND_DATA_GUIDE_IDX",
"dataguide": "on",
"search_on": "text_value"
}
col.createIndex(indexSpec);
console.log(`Search & Data Guide index successfully created`);
}
非定型(検索)の索引付けのみを高速化する場合は、フィールドdataguide
に値"off"を指定する必要があります。dataguide
索引付け機能が不要な場合は、同じ方法でこれをオフにできます。
例7-22 SODA for In-Database JavaScriptを使用した索引の削除
この例は、SodaCollection.dropIndex()
およびforce
オプションを使用してコレクションの既存の索引を削除する方法を示しています。
export function dropIndex(indexName) {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open the collection
const col = db.openCollection("employees_collection");
if ( col === null ) {
throw "'employees_collection' does not exist";
}
// drop the index
const result = col.dropIndex(indexName, {"force": true});
if (! result.dropped ) {
throw `Could not drop SODA index ${indexName}`;
}
}
SodaCollection.dropIndex()
は、単一のフィールドdropped
を含む結果オブジェクトを戻します。索引が削除された場合、その値はtrue
で、それ以外の場合はfalse
です。どちらの場合でもメソッドは正常に終了します。
オプションのパラメータ・オブジェクトをメソッドに指定できます。force
をtrue
に設定すると、基礎となるOracle Databaseドメイン索引で通常の削除が許可されない場合に、JSON索引の削除が強制されます。
SODA for In-Database JavaScriptを使用したコレクションのデータ・ガイドの取得
データ・ガイドは、一連のJSON文書に含まれる構造および型情報の概要を示します。これらの文書内で使用されているフィールドに関するメタデータを記録します。JSONドキュメントに対する優れたインサイトを提供し、データ・セットの概要把握に役立ちます。
SodaCollection.getDataGuide()
を使用してデータ・ガイドを作成できます。SODAでデータ・ガイドを取得するには、コレクションがJSONのみであり、"dataguide"
オプションが"on"
であるJSON検索索引を持っている必要があります。データ・ガイドは、sodaCollection.getDataGuide()
からSodaDocument
のJSONコンテンツとして戻されます。データ・ガイドは現在のコレクションの状態から推測されます。コレクションが大きくなったり、ドキュメントが変更されると、その後にgetDataGuide()
がコールされるたびに新しいデータ・ガイドが戻されます。
例7-23 コレクションのデータ・ガイドの生成
この例では、メソッドgetDataGuide()
を使用してコレクションemployees_collection
のデータ・ガイドを取得し、メソッドgetContentAsString()
を使用してコンテンツを文字列として出力します。
CREATE OR REPLACE MLE MODULE data_guide_mod
LANGUAGE JAVASCRIPT AS
import oracledb from "mle-js-oracledb";
export function createDataGuide() {
// get a connection handle to the database session
const connection = oracledb.defaultConnection();
// get a SODA database
const db = connection.getSodaDatabase();
// open the collection
const col = db.openCollection("employees_collection");
if ( col === null ) {
throw "'employees_collection' does not exist";
}
// generate a Data Guide
const doc = col.getDataGuide();
console.log(doc.getContentAsString());
}
/
SODA for In-Database JavaScriptによるトランザクションの処理
クライアント側のJavaScript SQLドライバとは異なり、MLE JavaScript SQLドライバはautoCommit
機能を提供していません。モジュール・コールの場合はPL/SQLレイヤーで、またはconnection.commit()
かconnection.rollback()
をコールすることでJavaScriptコードで直接的に、トランザクションをコミットまたはロールバックする必要があります。
注意:
コミットされていない操作でエラーが発生し、トランザクションを明示的にロールバックしない場合、不完全なトランザクションは、関連データを一貫性のない状態(コミットされていない部分的な結果)のままにする場合があります。SODA for In-Database JavaScriptの使用例の概要
SODA for In-Database JavaScriptの使用を最初から最後まで示すエンドツーエンドの例が含まれています。
Example 7-24 SODA for In-Database JavaScriptの使用
employeesCol
コレクションと対話するJavaScriptモジュールを定義します。- コレクションにJSONドキュメントを保持するJavaScriptファンクションを作成します。
- コレクションで見つかったすべての従業員をリストする別のJavaScriptファンクションを定義します。
- PL/SQLパッケージ内の各ファンクションへのコール仕様を指定します。
JavaScript モジュールの定義
このモジュールでは、グローバル・スコープで使用可能な変数を使用して、必要なコーディングの量を制限します。
CREATE OR REPLACE MLE MODULE employees_module
LANGUAGE JAVASCRIPT AS
/// <reference types="mle-js" />
const colName = "employeesCol";
/**
* add an employee document to the employeesCol collection
*
* @param {json} employeeDoc - the new employee document to be added
*/
export function addEmployee(employeeDoc) {
// this code example uses the SODA database object (soda)
// available in the global scope
const col = soda.createCollection(colName);
col.insertOne(employeeDoc);
}
/**
* return a JSON document containing all the employees from the collection
*
* @returns {json} a document listing employee_id, last name, and department_name
*/
export function findAllEmployees() {
// this array will contain all the employee documents
// shortened to include employee ID, last name and
// department name. It is safer to assume the array is
// empty at first
let employeeList = [];
const col = soda.openCollection(colName);
if ( col === null ) {
return employeeList;
}
// iterate over all documents in the collection
const allDocs = col.find().getDocuments();
for ( let doc of allDocs ) {
const payload = doc.getContent();
// add the relevant fields to a JSON document before
// pushing it to the employeeList array
const employeeDetail = {
"employee_id": payload.employee_id,
"last_name": payload.last_name,
"department_name": payload.department_name
};
employeeList.push(employeeDetail);
};
// return the list of employees found in the collection
return employeeList;
}
/
コール仕様の指定
JavaScriptモジュールemployees_module
で定義された両方のファンクションのコール仕様は、次のパッケージで提供されます。パッケージは、定義者権限ではなく実行者権限で定義されます。パッケージの実行者にはSODA_APP
ロールが付与されている必要があります。付与されていない場合、エラーがスローされます。
CREATE OR REPLACE PACKAGE employees_pkg
AUTHID current_user
AS
PROCEDURE add_employee(employee JSON)
AS MLE MODULE employees_module
SIGNATURE 'addEmployee';
FUNCTION find_all_employees
RETURN JSON
AS MLE MODULE employees_module
SIGNATURE 'findAllEmployees';
END employees_pkg;
/
コレクションへのサンプル・データの追加
次の匿名PL/SQLブロックは、HR.EMPLOYEES
からの2つの行をJSONドキュメントに変換し、前に作成したコール仕様によって外部化されたJavaScriptコードを起動してコレクションに挿入します。
DECLARE
l_employee JSON;
BEGIN
SELECT
JSON{
'employee_id' IS e.employee_id,
'first_name' IS e.first_name,
'last_name' IS e.last_name,
'email' IS e.email,
'phone_number' IS e.phone_number,
'hire_date' IS e.hire_date,
'job_id' IS e.job_id,
'salary' IS e.salary,
'commission_pct' IS e.commission_pct,
'manager_id' IS e.manager_id,
'department_name' IS d.department_name
}
INTO
l_employee
FROM
hr.employees e
JOIN hr.departments d ON (e.department_id = d.department_id)
WHERE
e.employee_id = 100;
employees_pkg.add_employee(l_employee);
SELECT
JSON{
'employee_id' IS e.employee_id,
'first_name' IS e.first_name,
'last_name' IS e.last_name,
'email' IS e.email,
'phone_number' IS e.phone_number,
'hire_date' IS e.hire_date,
'job_id' IS e.job_id,
'salary' IS e.salary,
'commission_pct' IS e.commission_pct,
'manager_id' IS e.manager_id,
'department_name' IS d.department_name
}
INTO
l_employee
FROM
hr.employees e
JOIN hr.departments d ON (e.department_id = d.department_id)
WHERE
e.employee_id = 101;
employees_pkg.add_employee(l_employee);
END;
/
コレクション内のすべての従業員の検索
最後に、EMPLOYEES_PKG.find_all_employees()
を使用して、コレクションに格納されている従業員の短縮リストを提供できます。
SELECT
JSON_SERIALIZE(
employees_pkg.find_all_employees
PRETTY
) AS all_employees;
/
結果:
ALL_EMPLOYEES
--------------------------------------------------
[
{
"employee_id" : 100,
"last_name" : "King",
"department_name" : "Executive"
},
{
"employee_id" : 101,
"last_name" : "Yang",
"department_name" : "Executive"
}
]