はじめに
本記事では、Node.jsからSimple Oracle Document Accessを使ってOracle Databaseへアクセスをする手順を紹介します。
SODA(Simple Oracle Document Access)とは
Simple Oracle Document Access (SODA)は、NoSQL形式のAPIセットです。
SODAを使用すると、Oracle Databaseのドキュメント(特にJSON)のコレクションを作成および格納でき、SQLや、ドキュメントがどのようにデータベースに格納されているかを理解していなくても、そのコレクションの取得や問合せを行うことができます。
様々な言語とRepresentational State Transfer (REST)アーキテクチャ・スタイルで使用するための別々のSODA実装があります。
今回は、Oracle Databaseをドキュメントストアとして使用し、Node.jsで作成したサンプルプログラムからドキュメントをロードするまでの手順をまとめます。
node-oracledbの特徴
- 以下のように、npmから簡単にインストール可能です。
npm install oracledb
- Node.js 10以降、および複数のOracleDatabaseバージョンをサポートします。
- SQL・PL / SQL文の実行、およびSODAドキュメントスタイルのアクセスAPIへのアクセスが可能です。
- ラージオブジェクト(CLOBおよびBLOB)およびSQLオブジェクトのバインディングを含む広範なOracleデータ型をサポートします。
- Connection Poolingを含む接続管理が可能です。
- OracleDatabaseの高可用性機能が使用できます。
- 暗号化されたネットワークトラフィックとセキュリティ機能を含む、Oracle NetworkServiceインフラストラクチャをフルに活用します。
Node-oracledbのアーキテクチャ
Node-oracledbは、Node.jsアプリケーションがOracleデータベースにアクセスできるようにするNode.jsのアドオンです。
Node.jsプログラムは、node-oracledb関数を呼び出します。
内部的にnode-oracledb関数により、Oracleクライアントライブラリが動的にロードされます。
これにより、node-oracledbからOracle Databaseへの接続が確立されるため、SQL、PL / SQL、およびSODAを使用できます。
前提
- 検証環境は下記の通りです
$ sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.5
BuildVersion: 18F132
$ node -v
v14.15.5
手順
ここからは、Oracle Databaseをドキュメントストアとして使用し、Node.jsで作成したサンプルプログラムからドキュメントをロードするまでの手順をまとめます。
前準備
Oracle Databaseのインストール
今回は、Oracle Database container imagesを使用します。
インストール方法はこちらをご覧ください。
バージョンは下記の通りです。
SQL> select banner from v$version;
BANNER
--------------------------------------------------------------------------------
Oracle Database 19c Enterprise Edition Release 19.0.0.0.0 - Production
Oracle Instant Clientのインストール
Node-oracledbはnpmからインストールが可能ですが、Oracle Clientは個別にインストールする必要があります。
今回は、Oracle Instant Clientを使用します。こちらから、以下2つの最新版パッケージをインストールします。
- Basic Package (ZIP)
- SQL*Plus Package (ZIP)
※Basic PackageとSQL*Plus Packageは、同一ディレクトリに展開する必要があります。
適切にインストールすると、下記のディレクトリ構成になります。
$ ls -lha
total 525576
drwxr-xr-x@ 34 root admin 1.1K 2 13 13:57 .
drwxr-xr-x 4 kohei staff 128B 2 13 14:19 ..
-r-xr-xr-x@ 1 root admin 5.6K 2 23 2019 BASIC_LICENSE
-rw-r--r--@ 1 root admin 1.6K 9 20 22:12 BASIC_README
-r-xr-xr-x@ 1 root admin 5.6K 2 23 2019 SQLPLUS_LICENSE
-rw-r--r--@ 1 root admin 1.6K 9 20 22:13 SQLPLUS_README
-rwxr-xr-x@ 1 root admin 9.7K 9 20 22:12 adrci
-rwxr-xr-x@ 1 root admin 39K 9 20 22:12 genezi
-r-xr-xr-x@ 1 root admin 342B 4 25 2015 glogin.sql
lrwxrwxrwx 1 root admin 20B 2 13 13:55 libclntsh.dylib -> libclntsh.dylib.19.1
lrwxrwxrwx 1 root admin 20B 2 13 13:55 libclntsh.dylib.10.1 -> libclntsh.dylib.19.1
lrwxrwxrwx 1 root admin 20B 2 13 13:55 libclntsh.dylib.11.1 -> libclntsh.dylib.19.1
lrwxrwxrwx 1 root admin 20B 2 13 13:55 libclntsh.dylib.12.1 -> libclntsh.dylib.19.1
lrwxrwxrwx 1 root admin 20B 2 13 13:55 libclntsh.dylib.18.1 -> libclntsh.dylib.19.1
-rwxr-xr-x@ 1 root admin 95M 9 9 16:28 libclntsh.dylib.19.1
-rwxr-xr-x@ 1 root admin 4.6M 9 9 16:28 libclntshcore.dylib.19.1
-rwxr-xr-x@ 1 root admin 8.0M 8 31 21:56 libnnz19.dylib
lrwxrwxrwx 1 root admin 18B 2 13 13:55 libocci.dylib -> libocci.dylib.19.1
lrwxrwxrwx 1 root admin 18B 2 13 13:55 libocci.dylib.10.1 -> libocci.dylib.19.1
lrwxrwxrwx 1 root admin 18B 2 13 13:55 libocci.dylib.11.1 -> libocci.dylib.19.1
lrwxrwxrwx 1 root admin 18B 2 13 13:55 libocci.dylib.12.1 -> libocci.dylib.19.1
lrwxrwxrwx 1 root admin 18B 2 13 13:55 libocci.dylib.18.1 -> libocci.dylib.19.1
-rwxr-xr-x@ 1 root admin 1.5M 9 9 19:10 libocci.dylib.19.1
-rwxr-xr-x@ 1 root admin 124M 9 20 22:12 libociei.dylib
-r-xr-xr-x@ 1 root admin 148K 9 9 19:06 libocijdbc19.dylib
-rwxr-xr-x@ 1 root admin 102K 9 9 18:37 liboramysql19.dylib
-r-xr-xr-x@ 1 root admin 1.3M 9 2 01:56 libsqlplus.dylib
-rwxrwxrwx@ 1 root admin 1.6M 9 20 22:07 libsqlplusic.dylib
-rw-r--r--@ 1 root admin 4.2M 5 20 2020 ojdbc8.jar
-rwxr-xr-x@ 1 root admin 8.3K 9 20 22:13 sqlplus
-rw-r--r--@ 1 root admin 1.6M 5 20 2020 ucp.jar
-rwxr-xr-x@ 1 root admin 147K 9 20 22:12 uidrvci
-rw-r--r--@ 1 root admin 73K 7 3 2020 xstreams.jar
tnsnames.oraの作成
動的にロードされたOracleクライアントライブラリに対して、接続先のOracle Databaseの情報を示します。
$ pwd
/Applications/ora/client/instantclient_19_8
$ mkdir -p network/admin
$ cd network/admin
$ vim tnsnames.ora
ORCLCDB=localhost:1521/ORCLCDB
ORCL=
(DESCRIPTION =
(ADDRESS = (PROTOCOL = TCP)(HOST = localhost)(PORT = 1521))
(CONNECT_DATA =
(SERVER = DEDICATED)
(SERVICE_NAME = ORCL)
)
)
環境変数の設定
Oracle Instant Clientを使用してOracle Databaseへ接続するための環境変数を設定します。
$ vim ~/.bash_profile
・・・
# Oracle Instant Client
export LD_LIBRARY_PATH=/Applications/ora/client/instantclient_19_8:$LD_LIBRARY_PATH
export PATH=$LD_LIBRARY_PATH:$PATH
export TNS_ADMIN=/Applications/ora/client/network/admin
テストユーザ作成、権限付与
実行中のdockerコンテナにログインし、テスト用ユーザの作成、必要な権限付与を行います。
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e85249e82ae4 oracle/database:19.3.0-ee "/bin/sh -c 'exec $O…" 3 weeks ago Up 6 hours (healthy) 0.0.0.0:1521->1521/tcp, 0.0.0.0:5500->5500/tcp oracle
$ docker exec -it oracle /bin/bash
[oracle@e85249e82ae4 ~]$
[oracle@e85249e82ae4 ~]$ sqlplus /nolog
SQL*Plus: Release 19.0.0.0.0 - Production on Sat Feb 13 08:10:26 2021
Version 19.3.0.0.0
Copyright (c) 1982, 2019, Oracle. All rights reserved.
SQL> conn sys/WElcome##01@ORCL as sysdba
Connected.
SQL> create user test identified by test
2 default tablespace users
3 temporary tablespace temp
4 quota unlimited on users;
User created.
SQL> grant connect, resource to test;
Grant succeeded.
SQL*Plusから接続確認
dockerコンテナ内で、作成したテスト用ユーザでOracle Databaseへ接続が可能であることを確認します。接続が可能であることを確認したら、dockerコンテナからログアウトします。
SQL> conn test/test@orcl;
Connected.
SQL> exit
[oracle@e85249e82ae4 ~]$ exit
exit
node-oracledbのインストール
Oracle Instant Clientをインストールした環境に、oracledbパッケージをインストールします。
今回は、node-oracledb version 5.1を使用します。
$ npm install oracledb
$ npm list --depth=0
/Users/kohei
├── oracledb@5.1.0
プログラム作成
作成したテスト用ユーザでOracle Databaseに接続し、データをInsertするサンプルプログラムを作成します。
const oracledb = require('oracledb');
const mypw = 'test';
oracledb.autoCommit = true;
async function run() {
let connection;
try {
connection = await oracledb.getConnection( {
user: "test",
password : mypw,
connectString: "localhost:1521/orcl"
});
// Create a new document collection
const soda = connection.getSodaDatabase();
const collectionName = 'nodb_soda_collection'; // Table Name
const myCollection = await soda.createCollection(collectionName);
// Insert a new document
const myContent = {name: "Kohei", address: {city: "Setagaya", Country: "Japan"}, pet: "Mocha"};
await myCollection.insertOne(myContent);
// Print
const filterSpec = {"pet": "Mocha"};
const myDocuments = await myCollection.find().filter(filterSpec).getDocuments();
myDocuments.forEach(function(element) {
const content = element.getContent();
console.log(content.name, ' has a pet "Mocha".');
});
} catch (err) {
console.log ('Error in processing:\n', err);
} finally {
if (connection) {
try {
await connection.close();
} catch (err) {
console.log('Error in closing connection:\n', err);
}
}
}
}
run();
実行
実行すると、以下の内容が標準出力されます。
サンプルプログラムがうまく実行されたことがわかります。
$ node mysoda.js
Kohei has a pet "Mocha".
テーブル確認
内部的に作成されたテーブルを確認します。
JSON_DOCUMENTがBLOBとして列定義されており、1件のデータが挿入されていることがわかります。
SQL> desc nodb_soda_collection;
Name Null? Type
----------------------------------------- -------- ----------------------------
ID NOT NULL VARCHAR2(255)
CREATED_ON NOT NULL TIMESTAMP(6)
LAST_MODIFIED NOT NULL TIMESTAMP(6)
VERSION NOT NULL VARCHAR2(255)
JSON_DOCUMENT BLOB
SQL> select count(*) from nodb_soda_collection;
COUNT(*)
----------
1
ドキュメントに格納されたデータを確認すると、サンプルプログラム内で指定したデータが格納されていることがわかります。
SQL> select t.json_document.name, t.json_document.address, t.json_document.pet from nodb_soda_collection t;
NAME ADDRESS PET
---------- ---------------------------------------- ----------
Kohei {"city":"Setagaya","Country":"Japan"} Mocha
おわりに
Node.jsからOracle Databaseにドキュメントをロードすることができました。
SODAは、他にも以下の言語をサポートしています。
Java、C(Oracle Call Interfaceを使用)、Node.js、Python、PL/SQL、SODA for REST
SODA API | 入手方法 |
---|---|
SODA for Java | Oracle Database 19c (19.6) JDBC Driver & UCP SODA for Java 1.1.7 |
SODA for C | Oracle Client 19.6 以降 SODA for C |
SODA for Node.js | Oracle Client 19.6 以降 node-oracledb |
SODA for Python | Oracle Client 19.6 以降 cx_Oracle 8 |
SODA for PL/SQL | AutonomousDB内に内包 |
SODA for REST | RESTful Servicesへのアクセス |
是非とも皆さんも触ってみてください!