はじめに
Node.js + NoSQL(Couchbase) を使ったアプリ開発をステップバイステップで解説していきます。本記事は、シリーズの初回として位置付けられます。
Node.jsコミュニティに向けて
なぜ、NoSQLデータベースを使うのか
NoSQLの中でも、ここで扱うドキュメント指向データベース(ドキュメントストア)は、データとしてJSONドキュメントを格納します。言わずもがなですが、JSONとは「JavaScript Object Notation」の略で、Node.jsアプリ開発のバックエンドデータベースとしてドキュメントストアを利用することは、MEANスタック(MongoDB、Express、AngularJS、Node.js)にもみられように、自然と言えます。
なぜ、Couchbaseを使うのか
NoSQL技術同士の比較については、この記事の目的ではないため、多くは触れません。
先にあげたMEANスタックからもわかるように、MongoDBがまずは筆頭に上がる状況を踏まえ、あまり目にする機会のない、日本語によるCouchbaseについての紹介として、興味を持っていただければ幸いです。
一つだけ、Couchbaseに独自の部分として、SQLのJSONドキュメント用の拡張である、Couchbaseのクエリ言語、N1QL(Non 1st-normal-form Query Language: 非第一正規化クエリ言語)の利用について、最後に解説します。
前提
- Node.js
- 開発環境がセットアップされている
- Couchbase Server
- 開発環境にインストールされている(
localhost
でアクセス可能) - 管理者ユーザが作成されている(ID:
Administrator
、パスワード:password
) - Bucket(
test
)が作成されている - コマンドラインツールにパスが通っている
- 開発環境にインストールされている(
動作確認環境
- Mac OS Catalina Version 10.15.6
- コマンドラインツールパス:
/Applications/Couchbase Server.app/Contents/Resources/couchbase-core/bin/
- コマンドラインツールパス:
- Node.js
- node v15.4.0
- npm 7.0.15
- Couchbase Server 7.0 BETA
プロジェクト準備
プロジェクト用のディレクトリを作成し、その中で作業を開始します。
はじめに下記を実行します。
$ npm init -y
package.jsonファイルが作成されます。
Couchbase SDKをインストールし、package.jsonに追記します。
$ npm install couchbase --save
package.jsonに以下のような依存関係が追記されます。
"dependencies": {
"couchbase": "^3.1.0"
}
プログラム作成
index.js
ファイルを作成し、以下の内容を追加していきます。
Couchbaseへの接続
const couchbase = require("couchbase");
const cluster = new couchbase.Cluster("couchbase://localhost", {
username: "Administrator",
password: "password",
});
バケットへの接続
const bucket = cluster.bucket("test");
const collection = bucket.defaultCollection();
サンプルデータ定義
const user = {
type: "user",
id: 1,
name: "田中",
};
ドキュメント登録関数定義
const upsertDocument = async (doc) => {
try {
const key = `${doc.type}_${doc.id}`;
const result = await collection.upsert(key, doc);
console.log("Upsert: ");
console.log(result);
} catch (error) {
console.error(error);
}
};
ドキュメント取得関数定義
const getDocumentByKey = async (key) => {
try {
const result = await collection.get(key);
console.log("Get: ");
console.log(result);
} catch (error) {
console.error(error);
}
};
処理実行部
upsertDocument(user);
getDocumentByKey("user_1");
プログラム実行
$ node index.js
下記のような結果が出力されます。
Upsert:
{
cas: CbCas { '0': <Buffer 00 00 05 1b f9 1e 51 16> },
token: CbMutationToken {
'0': <Buffer d8 18 d7 a9 dd 24 00 00 03 00 00 00 00 00 00 00 2f 00 00 00 00 00 00 00 74 65 73 74 00 00 00 00 28 a2 03 05 01 00 00 00 40 a2 03 05 01 00 00 00 28 a2 ... 230 more bytes>
}
}
Get:
{
cas: CbCas { '0': <Buffer 00 00 05 1b f9 1e 51 16> },
content: { type: 'user', id: 1, name: '田中' }
}
Ctrl+Dでプロセスを抜けてください。
実行結果確認
Couchbase Serverのコマンドラインツール(cbq
)を使って、登録されたデータを確認します。
$ cbq -u Administrator
Enter Password:
Connected to : http://localhost:8091/. Type Ctrl-D or \QUIT to exit.
クエリ(SELECT * from test;
)を実行してみます。
以下のようなエラーになりました。
cbq> SELECT * from test;
{
"requestID": "00fda8f3-d64e-4d8c-85c1-ad810f921bd2",
"errors": [
{
"code": 4000,
"msg": "No index available on keyspace test that matches your query. Use CREATE INDEX or CREATE PRIMARY INDEX to create an index, or check that your expected index is online."
}
],
"status": "fatal",
"metrics": {
"elapsedTime": "438.814µs",
"executionTime": "368.037µs",
"resultCount": 0,
"resultSize": 0,
"serviceLoad": 2,
"errorCount": 1
}
}
cbq>
メッセージ("No index available on keyspace test that matches your query. Use CREATE INDEX or CREATE PRIMARY INDEX to create an index, or check that your expected index is online.")にもある通り、クエリを実行するには、インデックスが作成されている必要があります。
プライマリインデックスを作成します。
cbq> CREATE PRIMARY INDEX test_primary ON test;
{
"requestID": "2c482905-b794-4092-bb0b-8d8cb76bc535",
"signature": null,
"results": [
],
"status": "success",
"metrics": {
"elapsedTime": "1.872931032s",
"executionTime": "1.872853887s",
"resultCount": 0,
"resultSize": 0,
"serviceLoad": 2
}
}
cbq>
先ほどのクエリを再度、実行します。
以下のようにクエリの結果が表示されました。
cbq> SELECT * from test;
{
"requestID": "9b80a8eb-3605-4ff8-84fb-0a435959e4e1",
"signature": {
"*": "*"
},
"results": [
{
"test": {
"id": 1,
"name": "田中",
"type": "user"
}
}
],
"status": "success",
"metrics": {
"elapsedTime": "78.632291ms",
"executionTime": "78.571384ms",
"resultCount": 1,
"resultSize": 113,
"serviceLoad": 2
}
}
結果("results"の値)が幾分冗長なので、以下のようにクエリを微修正して、実行します。
cbq> SELECT test.* from test;
{
"requestID": "14dae1e2-cf81-45ae-8c55-2f64ad975743",
"signature": {
"*": "*"
},
"results": [
{
"id": 1,
"name": "田中",
"type": "user"
}
],
"status": "success",
"metrics": {
"elapsedTime": "1.034558ms",
"executionTime": "969.805µs",
"resultCount": 1,
"resultSize": 73,
"serviceLoad": 2
}
}
最後に
今回の記事は以上です。
今回のプログラムでは、キーによるアクセスのみを扱い、クエリでのアクセスについては、コマンドラインツールのみで扱いましたが、クエリをプログラムで実行することも、当然可能です。また、クエリについては、今回紹介したような単純なものではなく、一般にSQLを使った開発で用いられているようなもっと複雑なものが利用可能です。これについては、今後の記事で紹介できればと思っています。
また、Node.jsの本来のあり方を考えると、上記のような一度だけ実行するプログラムを作成・実行することは、直感的ではないかもしれません。サーバ・プログラム化についても、今後の記事で紹介していきたいと考えています。
今回は、非常に単純なプログラムとして作成したことで、データベースへの接続と、データの登録・取得という、本質的な部分のみを見て行くことができたかと思います(Node.js経験者にとっては、それ以外の部分は、よく知られているところかとも思います)。また、MongoDBの経験者が読まれた際に、Couchbaseでの実装について、MongoDBと比べて、どのような違い(と共通点)があるかが分かりやすいものになっていれば幸いです。
最後に、ここで紹介したプログラムを下記に公開していますので、適宜ご参照・ご利用ください。