はじめに
Electron を使って作るスタンドアロンで動作するアプリのために、データベースエンジンに NeDB を使っています。
NeDB を使ってみた #JavaScript - Qiita
開発が継続されなくなったと聞いて、使用するのに躊躇を感じたりしていましたが、フォークされた後継版を見つけました。これを使ってみたいと思います。
NeDB とは
NeDB は、組込型の永続的あるいはインメモリのデータベースで、Node.js 、NW.js 、Electron およびブラウザで動作し、100 % JavaScript でバイナリ依存しません。API は MongoDB のサブセットで、非常に高速です。
フォークされた後継版を使用します。
公式 seald/nedb: The JavaScript Database, for Node.js, nw.js, electron and the browser
NeDB を使ってみた
- NeDB 4.1.2
インストールする
Node.js アプリのワークスペースにインストールします。
npm install @seald-io/nedb --save
データベースを作成する
インメモリのみ(データベース読込不要)
const Datastore = require('@seald-io/nedb');
const db = new Datastore();
永続的なデータストアに手動で読込
const Datastore = require('@seald-io/nedb');
const db = new Datastore({
filename: '◇◇/◆◆.db'
});
await db.loadDatabase();
ファイル名の拡張子は任意です。
ファイルはなければ自動で作成されます。
あれば読込まれます。
永続的なデータストアに自動で読込
const Datastore = require('@seald-io/nedb');
const db = new Datastore({
filename: '◇◇/◆◆.db',
autoload: true
});
メソッドの呼出の記述
従来の NeDB のメソッドは、実行の完了および返値をコールバックで受取します。
db.find({ ○○: ●● }, (err, docs) => {
if (err) {
....
}
....
});
後継版の NeDB は、Promise
を返すメソッドが追加されています。
db.findAsync({ ○○: ●● })
.then((docs) => {
....
})
.catch((err) => {
....
});
try {
const docs = await db.findAsync({ ○○: ●● });
....
}
catch (err) {
....
}
以降の説明は await
を使った記述します。
ドキュメントを挿入する
MongoDB もそうですが、NoSQL データベースでは、データの構成単位は「レコード」でなく「ドキュメント」なんですね。
var doc = {
○○: ●●,
....
};
const newDoc = await db.insertAsync(doc);
newDoc
は新規挿入されたドキュメント。
_id
フィールドが追加されます。これは 16 文字の英数文字列。変更は不可です。
ドキュメントの配列も挿入できます。
var docs = [
{ .... },
{ .... },
];
const newDocs = await db.insertAsync(docs, function(err, newDocs);
newDocs
は配列になります。
内容が同一のドキュメントは挿入できません。
ドキュメントを検索する
基本的な問合せ
指定した値と一致するドキュメントを検索
const docs = await db.findAsync({ ○○: ●● });
docs
はドキュメントの配列です。一致するドキュメントがなければ []
になります。
指定した文字列を「含む」ドキュメントを検索
const docs = await db.findAsync({ ○○: /●●/ });
条件を AND 指定してドキュメントを検索
const docs = await db.findAsync({ ○○: ●●, □□: ■■ });
条件を指定せず全てのドキュメントを検索
const docs = await db.findAsync({});
指定した値と一致するドキュメントの一つを検索
const docs = await db.findOneAsync({ ○○: ●● });
doc
は一致するドキュメントがなければ null
になります。
比較演算
指定した値より小さい
const docs = await db.findAsync({ ○○: { $lt: ●● } });
指定した値より小さいか等しい
const docs = await db.findAsync({ ○○: { $lte: ●● } });
指定した値より大きい
const docs = await db.findAsync({ ○○: { $gt: ●● } });
指定した値より大きいか等しい
const docs = await db.findAsync({ ○○: { $gte: ●● } });
指定した値のいずれかと一致する
const docs = await db.findAsync({ ○○: { $in: [●●, ■■] } });
指定した値と異なる
const docs = await db.findAsync({ ○○: { $ne: ●● } });
指定した値のいずれでもない
const docs = await db.findAsync({ ○○: { $nin: [●●, ■■] } });
指定したフィールドがある
const docs = await db.findAsync({ ○○: { $exists: true } });
正規表現を他の条件指定と合わせて使う。例えば
const docs = await db.findAsync({ ○○: { $regex: /●●/, $nin: [●●, ■■] } });
条件を論理演算
条件を OR 指定
const docs = await db.findAsync({ $or: [{ ○○: ●● }, { □□: ■■ }] });
条件を NOT 指定
const docs = await db.findAsync({ $not: { ○○: ●● } });
関数を使って条件指定
const docs = await db.findAsync({ $where: function(){ return this.○○ = ●●; } });
指定を組合せる。例えば
const docs = await db.findAsync({ $or: [{ ○○: ●● }, { □□: ■■ }], ○○: ×× });
並替など
並替
const docs = await db.findAsync({ .... }).sort({ ○○: 1 });
逆順に並替
const docs = await db.findAsync({ .... }).sort({ ○○: -1 });
複数フィールドを指定して並替
const docs = await db.findAsync({ .... }).sort({ ○○: 1, ◇◇: 1 });
先頭から指定した数だけ
const docs = await db.findAsync({ .... }).sort({ .... }).limit(●);
ドキュメントのフィールドを指定
指定したフィールドだけ
const docs = await db.findAsync({ .... }, { ○○: 1, □□: 1 });
指定したフィールドを除いて
const docs = await db.findAsync({ .... }, { ○○: 0, □□: 0 });
MongoDB と非互換の書き方
const docs = await db.findAsync({ .... }).projection({ ○○: 1, □□: 1 });
ドキュメントをカウントする
指定した条件に一致するドキュメントをカウント
const count = await db.countAsync({ .... });
条件を指定せず全てのドキュメントをカウント
const count = await db.countAsync({});
ドキュメントを更新する
ドキュメントの内容を別のに置換
const { numAffected } = await db.updateAsync({ .... }, { ○○: ●● }, { multi: .... });
指定されたフィールドの値が置換えられます。
指定されなかったフィールドは残らないので注意が必要です。
_id
は変更されずに保持されます。
既存のフィールドの値を置換
const { numAffected } = await db.updateAsync({ .... }, { $set: { ○○: ●● } }, { multi: .... });
指定されたフィールドの値が置換えられます。
指定されなかったフィールドと値は残ります。
フィールドを削除
await db.updateAsync({ .... }, { $unset: { ○○: true } }, {});
ドキュメントあるいはフィールドがあれば更新、なければ挿入
const { numAffected, affectedDocs, upsert } = await db.updateAsync({ .... }, { ○○: ●● }, { upsert: true });
ドキュメントを削除する
指定した条件のドキュメント一つを削除
const { numRemoved } = await db.removeAsync({ .... }, {});
指定した条件のドキュメント全てを削除
const { numRemoved } = await db.removeAsync({ ... }, { multi: true });
全てのドキュメントを削除
const { numRemoved } = await db.removeAsync({}, { multi: true });