NeDB を使ってみた

  • 73
    いいね
  • 1
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

Electron を使ってデスクトップアプリを作成しようとしています。ある程度のデータを保存しておいて検索したりしたいので、データベースエンジンを使用したいと思います。
ただし今回は、アプリと別にデータベースエンジンをインストールする必要があるのは避けたいと思いました。
Electron であれば、Web Storage や Indexed DB が使えるけれど、使い勝手がいいとは言えません。
アプリに組込できるタイプのデータベースエンジンを探しました。その中に NeDB がありました。

参考 Node.jsで使えるファイルDB"NeDB"のススメ

NeDB とは

NeDB は、組込型の永続的あるいはインメモリのデータベースで、Node.js 、NW.js 、Electron およびブラウザで動作し、100 % JavaScript でバイナリ依存しません。API は MongoDB のサブセットで、非常に高速です。

公式 louischatriot/nedb: Embedded datastore for node.js

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 のコマンドをよく知らないのと、完全な互換ではなさそうなので、整理を兼ねて記事にしておくことにしました。
これでも公式サイトのドキュメントの全部ではありません。自分が使うにはこれだけあれば十分かなと思って書きました。