前回の【node.js】socket.ioを使って簡単にチャットを作る方法の続きです。今回はチャットした内容をデータベースに保存する方法です。こうすることによって、一回ブラウザを閉じて再度開いた時に閉じる前のメッセージが残っていたり、途中から参加した人も今までのメッセージが読めるようになります。いくら保存できるようになったとしても、製品レベルには程遠く、脆弱性対策もしていないので、今回は、node.jsでMongoDBを使うことと、MongoDB のオブジェクトモデリングツールであるMongoose(マングース)の使い方のポイントだけを抑えて頂ければと思います。
今回のポイント
- Mongooseをインストールして簡単な使い方。
- チャットのメッセージを保存する。
- ブラウザを閉じてもメッセージが残っている。
- メッセージを削除する。
- 削除したメッセージは、相手にも削除されるようにする。
※予めMongoDBが使える状態にしててください。
必要なnode_modules
- ejs
- express
- mongoose
- socket.io
Mongooseのインストール
インストールはいつものnpmでめっちゃ簡単にインストールできます。
$ npm install mongoose
app.jsを編集
前回の【node.js】socket.ioを使って簡単にチャットを作る方法のソースからMongooseの追記だけをしたサンプルです。
app.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
| /**
* Module dependencies.
*/
var express = require('express')
, routes = require('./routes')
, mongoose = require('mongoose');
var app = module.exports = express.createServer();
// Configuration
app.configure(function(){
app.set('views', __dirname + '/views');
app.set('view engine', 'ejs');
app.use(express.bodyParser());
app.use(express.methodOverride());
app.use(express.cookieParser());
app.use(express.session({ secret: 'your secret here' }));
app.use(app.router);
app.use(express.static(__dirname + '/public'));
});
app.configure('development', function(){
app.use(express.errorHandler({ dumpExceptions: true, showStack: true }));
});
app.configure('production', function(){
app.use(express.errorHandler());
});
// Routes
app.get('/', routes.index);
app.listen(3000, function(){
console.log("Express server listening on port %d in %s mode", app.address().port, app.settings.env);
});
//mongoose
var Schema = mongoose.Schema;
var UserSchema = new Schema({
message: String,
date: Date
});
mongoose.model('User', UserSchema);
mongoose.connect('mongodb://localhost/chat_app');
var User = mongoose.model('User');
//socket
var io = require('socket.io').listen(app);
io.sockets.on('connection', function (socket) {
socket.on('msg update', function(){
//接続したらDBのメッセージを表示
User.find(function(err, docs){
socket.emit('msg open', docs);
});
});
console.log('connected');
socket.on('msg send', function (msg) {
socket.emit('msg push', msg);
socket.broadcast.emit('msg push', msg);
//DBに登録
var user = new User();
user.message = msg;
user.date = new Date();
user.save(function(err) {
if (err) { console.log(err); }
});
});
//DBにあるメッセージを削除
socket.on('deleteDB', function(){
socket.emit('db drop');
socket.broadcast.emit('db drop');
User.find().remove();
});
socket.on('disconnect', function() {
console.log('disconnected');
});
});
|
chat.jsを編集
chat.js1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| // Client
$(function() {
var socket = io.connect('http://localhost');
socket.on('connect', function() {
socket.emit('msg update');
});
$('#btn').click(function() {
var message = $('#message');
socket.emit('msg send', message.val());
});
$('#delete').click(function(){
socket.emit('deleteDB');
});
socket.on('msg push', function (msg) {
var date = new Date();
$('#list').prepend($('<dt>' + date + '</dt><dd>' + msg + '</dd>'));
});
//接続されたらDBにあるメッセージを表示
socket.on('msg open', function(msg){
//DBが空っぽだったら
if(msg.length == 0){
return;
} else {
$('#list').empty();
$.each(msg, function(key, value){
$('#list').prepend($('<dt>' + value.date + '</dt><dd>' + value.message + '</dd>'));
});
}
});
//DBにあるメッセージを削除したので表示も消す
socket.on('db drop', function(){
$('#list').empty();
});
});
|
ターミナルでMongoDBを起動します。
$ mongod
app.jsを起動します。
$ node app.js
上手く起動すれば、 http://localhost:3000
でアクセスできると思います。
解説します。
さて、ここでのポイントは、送られてきたメッセージをMongoDBに登録する作業です。はじめに、
mongoose = require('mongoose');
でMongooseをrequireします。
次はMongooseの初期設定です。MongoDBに保存するデータ型を設定します。今回は簡単なチャットなので、メッセージのString型と、日付のDate型だけ登録しておきます。
js1 2 3 4 5
| //mongoose
var UserSchema = new Schema({
message: String, //チャットのメッセージ
date: Date //メッセージの送受信時間
});
|
connectでMongoDBと接続しますが、今回もローカルなのでlocalhost、次はデータベース名です。「chat_app」としました。
js1
| mongoose.connect('mongodb://localhost/chat_app');
|
socket.ioが接続されたら、まずはMongoDBの中に既にメッセージがあるかチェックします。
js1 2 3
| User.find(function(err, docs){ //メッセージを探す。
socket.emit('msg open', docs); //返って来た値をemitする。
});
|
emitでchat.jsの方に命令が行きます。引数にメッセージの中身が入っているので、chat.jsで表示させてあげる記述をします。chat.jsを見て下さい。
chat.js1 2 3 4 5 6 7 8 9 10 11 12 13
| //chat.js
//接続されたらDBにあるメッセージを表示
socket.on('msg open', function(msg){
//DBが空っぽだったら
if(msg.length == 0){
return;
} else {
$('#list').empty();
$.each(msg, function(key, value){
$('#list').prepend($('<dt>' + value.date + '</dt><dd>' + value.message + '</dd>'));
});
}
});
|
ここのところですね。引数msgが空っぽならretuneで返して、入っていたらjQueryのeachでタグにして表示させる記述です。最初にempty()してあるのは、途中で誰かが入ってきたら実行されてしまうので、重複した内容が表示されるのを防ぐために、empty()して空にすることにしました。もう少しスマートなやり方がありそうですね・・・。次はメッセージを送った時の処理です。
app.js1 2 3 4 5 6 7 8 9 10 11 12
| //app.js
socket.on('msg send', function (msg) {
socket.emit('msg push', msg); //自分へemit。
socket.broadcast.emit('msg push', msg); //broadcastで相手側。
//DBに登録
var user = new User();
user.message = msg; //メッセージを代入。
user.date = new Date(); //時間を記録。
user.save(function(err) { //saveでMongoDBに登録。
if (err) { console.log(err); }
});
});
|
たったこれだけです。とても簡単ですね!次はMongoDBの内容を削除して、チャットの内容も削除する方法です。削除のボタンを押した時のイベントを設定します。
chat.js1 2 3 4
| //chat.js
$('#delete').click(function(){
socket.emit('deleteDB'); //emitしてapp.jsに伝えます。
});
|
app.js1 2 3 4 5 6 7
| //app.js
//DBにあるメッセージを削除
socket.on('deleteDB', function(){
socket.emit('db drop'); //表示を消すためにchat.jsに伝えます。
socket.broadcast.emit('db drop'); //broadcastで開いてる全員に伝えます。
User.find().remove(); //データベースを削除します。
});
|
chat.js1 2 3 4 5
| //chat.js
//DBにあるメッセージを削除したので表示も消す
socket.on('db drop', function(){
$('#list').empty(); //表示を消す。
});
|
今回は一気に全部のメッセージを消しましたが、もちろん個別に消すこともできますし、投稿した本人しか消せないようにすることもできます。
まとめ
MongoDBを使うとWEBアプリの表現の幅が一気に広がります。MongoDBはnode.jsと親和性が高いので、Mongooseを使って簡単にデータベースの操作ができます。チャットとしては完成度が低く、脆弱性対策もしていないので、このサンプルコードをそのまま公開するのは避けましょう。あくまでも、node.jsの可能性と、Mongooseの使い方だけを紹介だけなので、その辺はあしからず。