はじめに
Electron を使ってデスクトップアプリを作成しようとしています。ある程度のデータを保存しておいて検索したりしたいので、データベースエンジンを使用したいと思います。
ただし今回は、アプリと別にデータベースエンジンをインストールする必要があるのは避けたいと思いました。
Electron であれば、Web Storage や Indexed DB が使えるけれど、使い勝手がいいとは言えません。
アプリに組込できるタイプのデータベースエンジンを探しました。その中に NeDB がありました。
参考 [Node.jsで使えるファイルDB"NeDB"のススメ]
(http://www.slideshare.net/isamusuzuki54/dbne-db)
NeDB とは
NeDB は、組込型の永続的あるいはインメモリのデータベースで、Node.js 、NW.js 、Electron およびブラウザで動作し、100 % JavaScript でバイナリ依存しません。API は MongoDB のサブセットで、非常に高速です。
公式 [louischatriot/nedb: Embedded datastore for node.js]
(https://github.com/louischatriot/nedb)
NeDB を使ってみた
- NeDB 1.8.0
インストールする
Node.js アプリのワークスペースにインストールします。
npm install --save nedb
データベースを作成する
インメモリのみ(データベース読込不要)
var Datastore = require('nedb');
var db = new Datastore();
永続的なデータストアに手動で読込
var Datastore = require('nedb');
var db = new Datastore({
filename: '◇◇/◆◆.db'
});
db.loadDatabase();
あるいは
db.loadDatabase(function(err){
// コマンドが実行される
});
ファイル名の拡張子は任意です。
ファイルはなければ自動で作成されます。
あれば読込まれます。
永続的なデータストアに自動で読込
var Datastore = require('nedb');
var db = new Datastore({
filename: '◇◇/◆◆.db',
autoload: true
});
// 直ぐにコマンドが発行できる
複数コレクションを作成
var db = {};
db.◆◆ = new Datastore('◇◇/◆◆.db');
db.●● = new Datastore('◇◇/●●.db');
db.◆◆.loadDatabase();
db.●●.loadDatabase();
コレクションごとに読込する必要あります。非同期で実行されます。
ドキュメントを挿入する
MongoDB もそうですが、NoSQL データベースでは、データの構成単位は「レコード」でなく「ドキュメント」なんですね。
var doc = {
○○: ◇◇,
....
};
db.insert(doc);
あるいは
db.insert(doc, function(err, newDoc){
....
});
newDoc
は新規挿入されたドキュメント。
_id
フィールドが追加されます。これは 16 文字の英数文字列。変更は不可です。
ドキュメントの配列も挿入できます。
var docs = [
{ .... },
{ .... },
];
db.insert(docs, function(err, newDocs){
....
});
newDocs
は配列になります。
内容が同一のドキュメントは挿入できません。
ドキュメントを検索する
基本的な問合せ
指定した値と一致するドキュメントを検索
db.find({ ○○: ●● }, function(err, docs){
....
});
docs
はドキュメントの配列です。一致するドキュメントがなければ []
になります。
指定した文字列を「含む」ドキュメントを検索
db.find({ ○○: /●●/ }, function(err, docs){
....
});
条件を AND 指定してドキュメントを検索
db.find({ ○○: ●●, ◇◇: ◆◆ }, function(err, docs){
....
});
条件を指定せず全てのドキュメントを検索
db.find({}, function(err, docs){
....
});
指定した値と一致するドキュメントの一つを検索
db.findOne({ ○○: ●● }, function(err, doc){
....
});
doc
は一致するドキュメントがなければ null
になります。
比較演算
指定した値より小さい
db.find({ ○○: { $lt: ●● } }, function(err, docs){
....
指定した値より小さいか等しい
db.find({ ○○: { $lte: ●● } }, function(err, docs){
....
指定した値より大きい
db.find({ ○○: { $gt: ●● } }, function(err, docs){
....
指定した値より大きいか等しい
db.find({ ○○: { $gte: ●● } }, function(err, docs){
....
指定した値のいずれかと一致する
db.find({ ○○: { $in: [●●, ◆◆] } }, function(err, docs){
....
指定した値と異なる
db.find({ ○○: { $ne: ●● } }, function(err, docs){
....
指定した値のいずれでもない
db.find({ ○○: { $nin: [●●, ◆◆] } }, function(err, docs){
....
指定したフィールドがある
db.find({ ○○: { $exists: true } }, function(err, docs){
....
正規表現を他の条件指定と合わせて使う。例えば
db.find({ ○○: { $regex: /●●/, $nin: [◆◆, ■■] } }, function(err, docs){
....
条件を論理演算
条件を OR 指定
db.find({ $or: [{ ○○: ●● }, { ◇◇: ◆◆ }] }, function(err, docs){
....
条件を NOT 指定
db.find({ $not: { ○○: ●● } }, function(err, docs){
....
関数を使って条件指定
db.find({ $where: function(){ return this.○○ = ●●; } }, function(err, docs){
....
指定を組合せる。例えば
db.find({ $or: [{ ○○: ●● }, { ◇◇: ◆◆ }], □□: ■■ }, function(err, docs){
....
並替など
並替
db.find({ .... }).sort({ ○○: 1 }).exec(function(err, docs){
....
逆順に並替
db.find({ .... }).sort({ ○○: -1 }).exec(function(err, docs){
....
複数フィールドを指定して並替
db.find({ .... }).sort({ ○○: 1, ◇◇: 1 }).exec(function(err, docs){
....
先頭から指定した数だけ
db.find({ .... }).sort({ .... }).limit(●).exec(function(err, docs){
....
ドキュメントのフィールドを指定
指定したフィールドだけ
db.find({ .... }, { ○○: 1, ◇◇: 1 }, function(err, docs){
....
指定したフィールドを除いて
db.find({ .... }, { ○○: 0, ◇◇: 0 }, function(err, docs){
....
MongoDB と非互換の書き方
db.find({ .... }).projection({ ○○: 1, ◇◇: 1 }).exec(function(err, docs){
....
ドキュメントをカウントする
指定した条件に一致するドキュメントをカウント
db.count({ .... }, function(err, count){
....
});
条件を指定せず全てのドキュメントをカウント
db.count({}, function(err, count){
....
});
ドキュメントを更新する
ドキュメントの内容を別のに置換
db.update({ .... }, { ○○: ◆◆ }, { multi: .... }, function(err, numReplaced){
....
});
指定されたフィールドの値が置換えられます。
指定されなかったフィールドは残らないので注意が必要です。
_id
は変更されずに保持されます。
既存のフィールドの値を置換
db.update({ .... }, { $set: { ○○: ●● } }, { multi: .... }, function(err, numReplaced){
....
});
指定されたフィールドの値が置換えられます。
指定されなかったフィールドと値は残ります。
フィールドを削除
db.update({ .... }, { $unset: { ○○: true } }, {}, function () {
....
});
ドキュメントあるいはフィールドがあれば更新、なければ挿入
db.update({ .... }, { ○○: ●● }, { upsert: true }, function(err, numReplaced, upsert){
....
});
ドキュメントを削除する
指定した条件のドキュメント一つを削除する
db.remove({ .... }, {}, function(err, numRemoved){
....
});
指定した条件のドキュメント全てを削除する
db.remove({ ... }, { multi: true }, function(err, numRemoved){
....
});
全てのドキュメントを削除する
db.remove({}, { multi: true }, function(err, numRemoved){
....
});
おわりに
API が MongoDB のサブセットなので、新たなリファレンスは要らないとも思ったけれど、自分が MongoDB のコマンドをよく知らないのと、完全な互換ではなさそうなので、整理を兼ねて記事にしておくことにしました。
これでも公式サイトのドキュメントの全部ではありません。自分が使うにはこれだけあれば十分かなと思って書きました。