Node.jsからMongoDBを利用する
日付 タグ node.js mongodb カテゴリ node.js目次
Node.jsでnode-mongodb-nativeを使ってMongoDB
Node.jsからMongoDBに接続して扱うにはいくつか利用できるパッケージがあるようだが、 今回は標準的なnode-mongodb-nativeを利用してテストしてみる。
https://github.com/mongodb/node-mongodb-native - node-mongodb-native
MacへのMongoDBのインストールはこの前にやってあったので、MongoDBを利用するためにMongoDBのサービスを先に起動しておく。
( ==>
MacにNoSQLのMongoDBを入れて使ってみる
)
テストディレクトリ作成とnode-mongodb-nativeのインストール
node-mongotestというテストディレクトリを作成、npmでnode-mongodb-nativeをインストール。
$ mkdir node-mongotest
$ cd node-mongotest
$ npm init
$ npm install mongodb --save
これでnode-mongodb-nativeを使える準備ができた。
MongoDBへの接続方法の確認
node-mongodb-nativeでのMongoへの接続は、MongoClient.connect(url)
で接続できる。
自分のローカルMacで動いているMongoDBに接続するにはURLはmongodb://localhost/
とすれば良い。
今回テストで使用するDB名はmongo_test
、コレクション名はmemo
とした。
var MongoClient = require('mongodb').MongoClient;
const mongo_url = 'mongodb://localhost/';
const mongo_dbname = 'mongo_test';
const collection_name = 'memo';
let client;
const connectDB = async() => {
if(!client)
client = await MongoClient.connect(mongo_url,
{ useNewUrlParser: true, useUnifiedTopology: true });
}
const db = () => { return client.db(mongo_dbname); }
MongoDBへデータをINSERTする
まずは何にしてもドキュメント(データのこと)がないと始まらないので、まずはINSERTの方法について確認していく。
// 1つデータを追加する
const create = async (title, message) => {
await connectDB();
const collection = db().collection(collection_name);
await collection.insertOne({ title: title, message: message });
}
insertOne
にコレクションに追加したいデータを指定すれば良い。
ここではメモ的な内容を保存することを前提として、title
とmessage
を保存することにした。
MongoDBのデータをUPDATEする
// データをアップデートする
const update = async (title, message) => {
await connectDB();
const collection = db().collection(collection_name);
await collection.updateOne(
{ title: title },
{ $set: { title: title, message: message } });
}
updateOne
でコレクションに入っているtitle
でマッチするドキュメントでアップデートをかけている。
MongoDBのコレクションから1つSELECT
// データを1つ読み込む
const read = async (title) => {
await connectDB();
const collection = db().collection(collection_name);
const data = await collection.findOne({ title: title });
console.log(`data = ${util.inspect(data)}`);
}
findOne
でtitle
でマッチするドキュメントを1つ取り出している。
このメソッドはマッチするドキュメントが1つだけしかないとき、あるいは結果を1つだけ取り出したい時に使う。
MongoDBのコレクションから全部をSELECT
先ほどのfindOneは1つのドキュメントを取り出す関数だったが、全部取り出すにはcollection.find()を使えばいい。
// 全データを読む
const readall = async () => {
await connectDB();
const collection = db().collection(collection_name);
const docs = await new Promise((resolve, reject) => {
var docs = [];
collection.find().forEach(
doc => { docs.push(doc); },
err => {
if (err) reject(err);
else resolve(docs);
}
);
});
console.log(`data = ${util.inspect(docs)}`);
}
ただし、collection.find()で得られる結果はCursor(カーソル)であるため、
collection.find(query).forEach(function(doc) {
// handle
}, function(err) {
// done or error
});
のような形でforEach
でデータを処理している。
MongoDBのコレクションからデータをDELETE
コレクションからドキュメントを削除するには
const destroy = async (title) => {
await connectDB();
const collection = db().collection(collection_name);
const doc = await collection.findOne({ title: title });
if (!doc) {
throw new Error(`No data found for ${title}`);
} else {
await collection.findOneAndDelete({ title: title });
}
}
findOneAndDelete
でtitle
でマッチをかけてデータを削除だが、その前に該当するデータが存在するかどうかfindOneで検索をかけている。
MongoDBへの接続を解除
async function close() {
if (client) client.close();
client = undefined;
}
MongoDBヘの接続解除はclose()を呼べばいい。
通しでテストをしてみる
以上の処理にもとづいたテストサンプルを流してみる。
mongotest.js
var util = require('util');
var MongoClient = require('mongodb').MongoClient;
const mongo_url = 'mongodb://localhossst/';
const mongo_dbname = 'mongo_test';
const collection_name = 'memo';
let client;
const connectDB = async() => {
if(!client)
client = await MongoClient.connect(mongo_url,
{ useNewUrlParser: true, useUnifiedTopology: true, connectTimeoutMS: 5000});
}
const db = () => { return client.db(mongo_dbname); }
// 1つデータを追加する
const create = async (title, message) => {
await connectDB();
const collection = db().collection(collection_name);
await collection.insertOne({ title: title, message: message });
//console.log('create done');
}
// データをアップデートする
const update = async (title, message) => {
await connectDB();
const collection = db().collection(collection_name);
await collection.updateOne(
{ title: title },
{ $set: { title: title, message: message } });
//console.log('update done');
}
// データを1つ読み込む
const read = async (title) => {
await connectDB();
const collection = db().collection(collection_name);
const data = await collection.findOne({ title: title });
console.log(`data = ${util.inspect(data)}`);
//console.log('read done');
}
// 全データを読む
const readall = async () => {
await connectDB();
const collection = db().collection(collection_name);
const docs = await new Promise((resolve, reject) => {
var docs = [];
collection.find({}).forEach(
doc => { docs.push(doc); },
err => {
if (err) reject(err);
else resolve(docs);
}
);
});
console.log(`data = ${util.inspect(docs)}`);
//console.log('readall done');
}
// データを削除する
const destroy = async (title) => {
await connectDB();
const collection = db().collection(collection_name);
const doc = await collection.findOne({ title: title });
if (!doc) {
throw new Error(`No data found for ${title}`);
} else {
await collection.findOneAndDelete({ title: title });
}
//console.log('destroy done');
}
async function close() {
if (client) client.close();
client = undefined;
//console.log('close done');
}
(async () => {
try {
console.log('********* Add 3 items *********');
await create('yesterday', 'go to school');
await create('today', 'watch a movie');
await create('tomorrow', 'play baseball');
await readall();
console.log('******** update 1 item *********');
await update('today', 'watch TV');
await readall();
console.log(' ******** select 1 item *********');
await read('tomorrow');
console.log('******** delete 1 item *********');
await destroy('today');
await readall();
} catch(err) {
console.log('******** error handling *********');
console.error(err);
} finally {
console.log('********* all tests done *********');
await close();
}
})();
実行した結果は以下の通り。
$ node mongotest.js
********* Add 3 items *********
data = [
{
_id: 5fba15a745613070bb19c8af,
title: 'yesterday',
message: 'go to school'
},
{
_id: 5fba15a745613070bb19c8b0,
title: 'today',
message: 'watch a movie'
},
{
_id: 5fba15a745613070bb19c8b1,
title: 'tomorrow',
message: 'play baseball'
}
]
******** update 1 item *********
data = [
{
_id: 5fba15a745613070bb19c8af,
title: 'yesterday',
message: 'go to school'
},
{
_id: 5fba15a745613070bb19c8b0,
title: 'today',
message: 'watch TV'
},
{
_id: 5fba15a745613070bb19c8b1,
title: 'tomorrow',
message: 'play baseball'
}
]
******** select 1 item *********
data = {
_id: 5fba15a745613070bb19c8b1,
title: 'tomorrow',
message: 'play baseball'
}
******** delete 1 item *********
data = [
{
_id: 5fba15a745613070bb19c8af,
title: 'yesterday',
message: 'go to school'
},
{
_id: 5fba15a745613070bb19c8b1,
title: 'tomorrow',
message: 'play baseball'
}
]
********* all tests done *********
ドキュメント追加、参照、削除がきちんとできたことが確認できた。
Expressと組み合わせたりすれば、サーバー処理でMongoDBに接続してデータを保存する処理が可能になるだろう。