Nodeにおける初のオブジェクトデータベース: Realm Node.js
RealmではこれまでモバイルデベロッパーにフォーカスしてRealm Mobile DatabaseをSwift、Objective-C、Java、XamarinとReact Nativeに対して開発し、オープンソースとして提供してきました。本日、完全に新しい挑戦としてRealm Node.jsをリリースします。Nodeにおける初の真のオブジェクトデータベースです。本日から無料で完全にオープンソースとしてリポジトリが公開され、NPMを用いて npm install --save realm
を実行するだけで利用できます。
これまで何年もの間、モバイルデベロッパーのみなさまから、サーバーサイドで動作するRealmが欲しいという本当にたくさんのご要望をいただいていました。長い間タスクリストに残ったままで、優先度は高くありませんでした。しかし、その状況はRealm Mobile Platformを9月にリリースしたことにより変わりました。何人ものお客さまから、Node APIについてお問い合わせをいただきました。私たちは、非常に迅速に(およそ2、3日)Nodeにおけるプラットフォーム戦略を策定し、Realm Node.jsを完成させました。
どういうもので、誰のためのものですか?
Realmはオブジェクトデータベースです。そのため、以前からオブジェクト指向でオブジェクトを扱っていたのと同様に、簡単にオブジェクトとしてデータを扱うことができます。異なるのは、オブジェクトがディスクに簡単に、かつ効率的に永続化されるということです。JSONにシリアライズする必要はなく、テーブルに表示するためにORMを使う必要もありません。ただオブジェクト指向開発における原則を守っているだけでいいのです。そしてすべてのモバイルクライアントサイドのプラットフォーム上で動作します。さらにこれからは、サーバーサイドのNode.js上でも動作します。
モバイルデベロッパーの方々にとっては、Realm Node.jsを用いて、事前にデータを入力しておいたRealmをマスターデータとしてクライアントに送信できます。これは、面倒なアプリサイズ制限を回避することができるなど、非常に便利です。これはモバイルデベロッパーのみなさまが何年も昔から求めていることです。
しかし、初期バージョンをバックエンドデベロッパーの方に見せたところ、当初考えていたよりもNodeコミュニティにとってもっと広く役立つかもしれないとわかったので、より興味深くなってきました。例えば、複数のNodeインスタンス間でライブデータを共有できると便利です。このことを説明するために、1つのマシン上で2つのNodeプロセスを動かしながら、Realmを用いるとシリアライズも、デシリアライズも必要なく、データが共有できるというデモを作成しました。
Realmのユニークな機能の1つはリアクティブアーキテクチャです。Realmはマルチバージョン同時実行制御を使用して、スレッドとプロセス間におけるデータベースへの並列アクセスを提供します。このことにより、読み取りは決して書き込みをブロックせず、一貫したデータベースのビューを保持することでACID準拠を保証します。並行アクセスのためにRealmは通知の仕組みを使って、書き込みトランザクションが完了すると、アクセッサ(ビュー)を更新します。デベロッパーは、通知のAPIを利用して、データの変更をリアクティブに反映することができます。下記のサンプルコードでは、Node.jsデベロッパーがプロセス間通信にRealmの通知を利用して、2つの独立したサービス間でデータをやりとりする方法を示しています。
サンプルコードでは、2つの著名なNode.jsライブラリであるExpressをWebフレームワークに、ログ出力のライブラリにWinstonを使用しています。Expressを使ってHTTPエンドポイントを作成し、Winstonを使ってリクエストに関する情報を記録します。
var express = require('express'),
util = require('util'),
winston = require('winston');
RealmWinston = require('./winston-realm').Realm;
var app = express();
// Use custom Winston transport: RealmWinston
// Writes log data to winston.realm
winston.add(RealmWinston, {});
app.get('/', function (req, res) {
res.send('Hello World!');
winston.info('Handled Hello World');
});
app.use(function (req, res, next) {
res.status(404).send('Sorry can not find that!');
winston.error('404 Error at: ' + req.url);
})
app.listen(3000, function () {
console.log('Example app listening on port 3000!');
});
Realmのメリットを活用できるように、ログデータをRealmに保存するWinstonのカスタムプラグインを作成しました。ルートに対するアクセスでは“Hello World”をレスポンスとして返します。その他のパスに対するアクセスについては、404エラーを返し、対応するパスをエラーメッセージに記録します。Realmにログデータを保存することで、Realmの通知リスナーとして登録された別のNodeプロセスを開始し、変更に反応することができるようになります。
'use strict';
var Realm = require('realm');
let winstonRealm = new Realm({
path: 'winston.realm'
});
// Register listener to print out log messages at error level
winstonRealm.objects('Log').filtered('level = "error"').addListener((logs, changes) => {
changes.insertions.forEach((index) => {
let log = logs[index];
console.log(log.message);
})
});
リスナーはRealmのコレクション通知を利用します。コレクション通知を用いると、追加・削除、または変更されたオブジェクトに対応するインデックスを知ることができます。サンプルコードでは、エラーレベルのすべてのログを取得するクエリにリスナーを追加し、ログメッセージをコンソールに出力しています。
サンプルコードは単純ですが、この機能は、マイクロサービスアーキテクチャ全体でデータをやりとりするような、より高度な応用も可能です。こちらの完全なデモをご覧ください。あなたのNode.jsプロジェクトでRealmを使い始めるなら、React NativeのドキュメントとAPIドキュメントをまずご覧ください。(コードベースはすべてのJavaScriptプラットフォームで共有されています)。
Realm Node.jsで他に特筆すべきことがありますか?ローカルメモリよりも大きなデータセットが利用できます。データに対しては通知やクエリが利用できます。複数のNodeインスタンスをまたがって、リアクティブなアーキテクチャを構築することができます。Dockerイメージ間でデータをやりとりすることもできるでしょう。ぜひ、いろいろな使い方を私たちに教えてください!