CRUDをnodejsとmongodbでやってみる
前提
以下を導入済みとします。
- MongoDB Compass
- Nodejs
この記事の対象
- APIプログラミングに不慣れでいきなりAPIを使うのは、利用制限や課金が怖く気が引ける
- nodejsを用いた定期的に何かを実行する処理の実装をざっくり知りたい
プロジェクト作成とパッケージインストール
npm init --yes
npm install express mongoose faker
モデルの定義と作成
今回は架空のイベント情報を格納するデータベースを作成する。
はじめにイベント情報として、イベント名・開始日時・開催状況の3つのフィールドを持つモデルを定義する。
//Require Mongoose
const mongoose = require("mongoose")
//Define a schema
const eventSchema = new mongoose.Schema({
eventName: {
type: String
},
closingTime: {
type: Date
},
isFinished: {
type: Boolean
}
})
class Event {
static insertBulkData(data) {
//mongoose Schema
return this.insertMany(data)
}
}
// methods from class into schema
eventSchema.loadClass(Event)
// Compile model from schema
module.exports = mongoose.model('Event', eventSchema)
参考:
CRUDをやってみる
Create編
今回の目的はあくまでCRUDなのでイベント情報は自動で生成する。
ここでは、fakerでランダムに生成したデータをMongoDBに挿入する。
fakerによる挿入データのランダム生成
※eventNameなどのキー名はModel.js
で定義したschemaのものと一致させる。
let record = {
eventName: `${faker.address.city()} ${faker.animal.type()} festival`,
closingTime: faker.date.soon(),
isFinished: false
}
全体
const express = require('express');
const mongoose = require('mongoose');
const app = express();
const faker = require('faker');
const model = require('./Model')
mongoose.connect('mongodb://localhost:27017/nodeschedulerExample').then((res) => {
console.log('mongoose connected successfully');
app.get("/insertdata", async (req, res) => {
let data = []
for (let i = 0; i < 100; i++) {
let record = {
eventName: `${faker.address.city()} ${faker.animal.type()} festival`,
closingTime: faker.date.soon(),
isFinished: false
}
data.push(record)
}
await model.insertBulkData(data)
res.send("Data is inserted")
})
app.listen(4000, () => {
console.log("Server is running port 4000");
})
}).catch((err) => {
console.error(err);
})
Createの実行
ブラウザで以下のURLを開く。
http://localhost:4000/insertdata
実行に成功するとData is insertedと表示される。
次にデータを確認するため、MongoDB Compassを開く。
nodeschedulerEventDataというデータベースが新規作成され、
その中にeventsというコレクションが新規作成される。
Update編
Updateの実装
架空のイベント情報として、以下のようにモデルを定義しました。
const eventSchema = new mongoose.Schema({
eventName: {
type: String
},
closingTime: {
type: Date
},
isFinished: {
type: Boolean
}
})
このうちclosingTimeとisFinishedを用いて、
「closingTimeが現在時刻を過ぎたイベントに終了フラグ(isFinishedをtrue)を設定」
という更新(Update)を実装します。
今回は先程のCreateのように、手動で実行するのではなくCronを使って自動で定期実行します。
パッケージを追加でインストール
npm install node-cron
このnode-cronを使ってスケジューラーを実装します。
scheduler.js
というファイルを新規作成します。
const mongoose = require('mongoose');
const model = require('./Model');
const cron = require('node-cron');
mongoose.connect('mongodb://localhost:27017/nodeschedulerExample').then((res) => {
console.log('mongoose connected successfully');
cron.schedule("*/20 * * * * *", async () => {
console.log("スケジューラータスクを実行")
})
}).catch((err) => {
console.error(err);
})
データベースからclosingTimeが現在時刻を過ぎたイベントを探し、
ステータスを更新するメソッドをEventクラスに追加します。
static archivEvent(date){
return this.updateMany({
closingTime : {
'$lte' :new Date(date)
}
},{
$set : {
isFinished : true
}
}).exec();
}
スケジューラーと組み合わせ、Updateを定期的に実行します。
closingTimeがスケジューラー実行時点より前の場合にアップデートされます。
動作確認のため、実行間隔は短めの20秒にしてます。
const mongoose = require('mongoose');
const model = require('./Model');
const cron = require('node-cron');
mongoose.connect('mongodb://localhost:27017/nodeschedulerExample').then((res) => {
console.log('mongoose connected successfully');
cron.schedule("*/20 * * * * *", async () => {
console.log("スケジューラータスクを実行します")
const d = new Date();
console.log(`次の日時より前のイベントをアーカイブ:${d}`)
const result = await model.archiveEvent(d)
const modifiedCount = result.modifiedCount
console.log(`一致:${modifiedCount}件`)
if (modifiedCount > 0) {
console.log(`scheduler => 終了したイベントをアーカイブしました`);
}
})
}).catch((err) => {
console.error(err);
})
Updateの実行
スケジューラーを起動します。
node scheduler.js
20秒間隔でメッセージが表示され、Updateが自動で実行されます。
今回はclosingTimeとしてfaker.date.soon()
を用いて日付をランダムに生成していますが、これは数時間〜数日後となっているので、少しずつUpdateされていくはずです。
もし中々Updateされない場合Createを担うプログラムを起動します。
node index.js
起動したらhttp://localhost:4000/insertdata
より、データを増やしてみてください。
Delete編
Deleteの実装
先程のUpdate編では終了時間(closingTime)が過去のデータに終了フラグ(isFinished)を設定する処理をスケジューラーによる自動化した。
これに加え、一定の期間が経ったデータを削除する処理を実装する。
現在作成中…