setup.js:初始化数据库

var util = require('util');
var async = require('async'); //npm install async
var notesdb = require('./nodesdb-sqlite3');
// var notesdb = require('./notesdb-mongoose'); notesdb.connect(function(error){
if (error) throw error;
});
notesdb.setup(function(error){
if (error){
util.log('ERROR ' + error);
throw error;
}
async.series([ //async.series函数可以控制函数按顺序执行,从而保证最后的函数在所有其他函数完成之后执行
function(cb){
notesdb.add("test", "testtest",
function(error){
if (error) util.log('ERROR ' + error);
cb(error);
});
}
],
function(error, results){
if (error) util.log('ERROR ' + error);
notesdb.disconnect(function(err){});
}
);
});

nodesdb-sqlite3.js

SQLite3 是一个轻量级的进程内SQL引擎
它是一个无服务器且无需配置的SQL数据库引擎,仅仅是作为一个独立的库被链接到应用程序上

npm install sqlite3 安装此模块之前先在系统上安装sqlite3库 http://www.sqlite.org/download.html 下载

//数据库接口库
var util = require('util');
var sqlite3 = require('sqlite3'); sqlite3.verbose();
var db = undefined; /*
数据库名是直接硬编码的,所以当调用connect和setup函数时,当前目录中就会生成chap06.sqlite3文件
*/ exports.connect = function(callback){
db = new sqlite3.Database("chap06.sqlite3", sqlite3.OPEN_READWRITE | sqlite3.OPEN_CREATE,
function(err){
if (err){
util.log('FAIL on creating database ' + err);
callback(err);
} else {
callback(null);
}
});
} //此处的disconnect函数是空的
exports.disconnect = function(callback){
callback(null);
} exports.setup = function(callback){
db.run("CREATE TABLE IF NOT EXISTS notes " +
"(ts DATETIME, author VARCHAR(255), note TEXT)",
function(err){
if (err){
util.log('FAIL on creating table ' + err);
callback(err);
} else {
callback(null);
}
});
} exports.emptyNote = {"ts": "", author: "", note: ""};
exports.add = function(author, note, callback){
db.run("INSERT INTO notes (ts, author, note) " +
"VALUES (?, ?, ?);",
[new Date(), author, note],
function(error){
if (error){
util.log('FAIL on add ' + error);
callback(error);
} else {
callback(null);
}
});
}
/*
run函数接受一个字符串参数,其中?表示占位符,占位符的值必须通过一个数组传递进来
调用者提供了一个回调函数,然后通过这个回调函数来声明错误
*/ exports.delete = function(ts, callback){
db.run("DELETE FROM notes WHERE ts = ?;",
[ts],
function(err){
if (err){
util.log('FAIL to delete ' + err);
callback(err);
} else {
callback(null);
}
});
} exports.edit = function(ts, author, note, callback){
db.run("UPDATE notes " +
"SET ts = ?, author = ?, note = ? " +
"WHERE ts = ?",
[ts, author, note, ts],
function(err){
if (err){
util.log('FAIL on updating table ' + err);
callback(err);
} else {
callback(null);
}
});
} exports.allNotes = function(callback){
util.log(' in allnote');
db.all("SELECT * FROM notes", callback);
}
exports.forAll = function(doEach, done){
db.each("SELECT * FROM notes", function(err, row){
if (err){
util.log('FAIL to retrieve row ' + err);
done(err, null);
} else {
doEach(null, row);
}
}, done);
}
/*
allNotes和forAll函数是操作所有数据的两种方法,allNotes把数据库中所有的数据行收集到一个数组里,
而forAll方法可以接受两个回调函数,每当从数据集中拿一行数据,回调函数doEach都会执行一遍,当读完所有数据时,回调函数done就会执行
*/ exports.findNoteById = function(ts, callback){
var didOne = false;
db.each("SELECT * FROM notes WHERE ts = ?",
[ts],
function(err, row){
if (err){
util.log('FAIL to retrieve row ' + err);
callback(err, null);
} else {
if (!didOne){
callback(null, row);
didOne = true; //保证回调函数只被执行一次
}
}
});
}

notesdb-mongoose.js

MongoDB是nosql数据库的领头羊之一,"可扩展、高性能、开源、面向文档的数据库",它使用JSON风格的文档。
Mongoose是用于访问MongoDB的模块之一,它是一个对象建模工具,意味着你的程序负责定义模式对象来描述数据,
而Mongoose负责数据到MongoDB的存储。
Mongoose对于Node和MongoDB而言是一个非常强大的对象建模工具,使用嵌入式文档,是一个类型灵活的系统,
适用于字段输入、字段验证、虚拟字段等。

MongoDB Windows 下安装部署 http://www.cnblogs.com/EricaMIN1987_IT/p/3571773.html
安装Mongoose模块 npm install mongoose

Mongoose不是唯一一个在node中使用MongoDB的工具。

var util = require('util');
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var dburl = 'mongodb://localhost/chap06'; //dburl用于连接已运行的MongoDB exports.connect = function(callback){
mongoose.connect(dburl);
}
exports.disconnect = function(callback){
mongoose.disconnect(callback);
} exports.setup = function(callback){callback(null);} //定义模式
var NoteSchema = new Schema({
ts: {type: Date, default: Date.now}, //默认值
author: String,
note: String
});
//将NoteSchema作为Mongoose的模型注册进去
mongoose.model('Note', NoteSchema);
var Note = mongoose.model('Note'); exports.emptyNote = {"_id": "", author: "", note: ""}; exports.add = function(author, note, callback){
var newNote = new Note();
newNote.author = author;
newNote.note = note;
newNote.save(function(err){
if (err){
util.log('FATAL ' + err);
callback(err);
} else {
callback(null);
}
});
} exports.delete = function(id, callback){
exports.findNoteById(id, function(err, doc){
if (err){
callback(err);
} else {
util.log(util.inspect(doc));
doc.remove();
callback(null);
}
});
} exports.edit = function(id, author, note, callback){
exports.findNoteById(id, function(err, doc){
if (err){
callback(err);
} else {
doc.ts = new Date();
doc.author = author;
doc.note = note;
doc.save(function(err){
if (err){
util.log('FATAL ' + err);
callback(err);
} else {
callback(null);
}
});
}
});
} exports.allNotes = function(callback){
Note.find({}, callback);
} exports.forAll = function(doEach, done){
Note.find({}, function(err, docs){
if (err){
util.log('FATAL ' + err);
done(err, null);
}
docs.forEach(function(doc){
doEach(null, doc);
});
done(null);
});
} /*
_id字段是MongoDB提供的全局唯一的ID,用于标识存储的文档
*/
var findNoteById = exports.findNoteById = function(id, callback){
Note.findOne({_id: id}, function(err, doc){
if (err){
util.log('FATAL ' + err);
callback(err, null);
}
callback(null, doc);
});
}

app.js

//在数据库需要放置在一台计算机上时,应该考虑使用SQLite3
//控制器,在nodesdb-sqlite3.js和notesdb-mongoose.js模块之间切换
var util = require('util');
var url = require('url');
var express = require('express');
var nmDbEngine = 'sqlite3'; //用于命名数据库引擎、选择合适的notesdb实现和选择合适的views目录
//var nmDbEngine = 'mongoose';
var notesdb = require('./nodesdb-' + nmDbEngine);
var app = express();
app.use(express.logger());
app.use(express.cookieParser()); //添加cookieParser中间件
app.use(express.bodyParser());
app.engine('.html', require('ejs').__express); //3.X
//app.register('.html', require('ejs')); //2.X
app.set('views', __dirname + '/views-' + nmDbEngine);
app.set('view engine', 'ejs'); //是一个路由中间件函数,用于在一些路由器函数中解析URL查询参数
var parseUrlParams = function(req, res, next){
req.urlP = url.parse(req.url, true);
next();
} //检查用户是否被允许访问,这里只检查cookie是否等于AOK,这个单词通常意味着一切都没问题
/*
很多应用都需要用户登录,然后用户才能进行一些特权操作。由于HTTP是一个无状态的协议,
验证用户的唯一方式就是发送一个cookie到浏览器上,然后验证标识符。cookie包含了应用中用于验证用户的数据。 cookieParser中间件在这里做了很多工作,查找cookie,解析cookie,然后将解析出来的值让到req对象中。
当存在cookie时,它的值会被放入req.cookies中。
*/
var checkAccess = function(req, res, next){
if (!req.cookies || !req.cookies.notesaccess || req.cookies.notesaccess !== "AOK"){
res.redirect('/login');
} else {
next();
}
} notesdb.connect(function(error){
if (error) throw error;
}) app.on('close', function(error){
notesdb.disconnect(function(err){});
}); app.get('/', function(req, res) {res.redirect('/view');});
app.get('/view', checkAccess, function(req, res){ //可以在每个路由上加checkAccess检查
notesdb.allNotes(function(err, notes){
if (err){
util.log('ERROR ' + err);
throw err;
} else {
res.render('viewnotes.html', {title: "Notes ("+ nmDbEngine +")", notes: notes});
}
});
}); /*
当用户点击ADD按钮时app.get('/add', ...)内的函数就会被调用,浏览器会发出一个发往/add的HTTP GET请求。
这个函数使用addedit.html模板来创建一个表单,让用于通过这个表单输入标签,然后通过单击SUBMIT按钮提交,
当用户提交表单,浏览器就会发出一个HTTP POST请求,app.post('/add', ...)内的函数就会被调用,
用户输入的数据会被存放在请求主体中,而请求主体会被bodyParser(app.use(express.bodyParser()))中间件处理并存放在req.body中
*/
app.get('/add', function(req, res){
res.render('addedit.html', {title: "Notes ("+ nmDbEngine +")", postpath: '/add', note: notesdb.emptyNote});
});
app.post('/add', function(req, res){
notesdb.add(req.body.author, req.body.note,
function(error){
if (error) throw error;
res.redirect('/view');
});
}); app.get('/del', parseUrlParams, function(req, res){
notesdb.delete(req.urlP.query.id,
function(error){
if (error) throw error;
res.redirect('/view');
});
}); app.get('/edit', parseUrlParams, function(req, res){
notesdb.findNoteById(req.urlP.query.id,
function(error, note){
if (error) throw error;
res.render('addedit.html',
{title: "Notes ("+ nmDbEngine +")", postpath: '/edit', note: note});
});
});
app.post('/edit', function(req, res){
notesdb.edit(req.body.id, req.body.author, req.body.note,
function(error){
if (error) throw error;
res.redirect('/view');
});
}); app.get('/login', function(req, res){
res.render('login.html', {title: "Notes LOGIN ("+ nmDbEngine +")"});
});
app.post('/login', function(req, res){
//此处可以添加检查用户信息的逻辑
//...
res.cookie('notesaccess', 'AOK');
res.redirect('/view');
}); app.listen();

show.js

//控制台显示
var util = require('util');
var notesdb = require('./notesdb-sqlite3');
// var notesdb = require('./notesdb-mongoose'); notesdb.connect(function(error){
if (error) throw error;
});
notesdb.forAll(function(error, row){
util.log('ROW: ' + util.inspect(row));
}, function(error){
if (error) throw error;
util.log('ALL DONE');
notesdb.disconnect(function(err){});
});

前台页面在views-sqlite3目录下

layout.html

<!DOCTYPE html>
<html>
<head>
<title><%= title%></title>
</head>
<body>
<h1><%= title%></h1>
<p><a href='/view'>View</a> | <a href='/add'>Add</a></p>
</body>
</html>

viewnotes.html

<% include layout.html %>
<table><% notes.forEach(function(note){ %>
<tr>
<td>
<p><%=new Date(note.ts).toString()%>: by <b><%=note.author%></b></p>
<p><%=note.note%></p>
</td>
<td>
<form method="get" action="/del">
<input type="submit" value="Delete" />
<input type="hidden" name="id" value="<%=note.ts%>" />
</form>
<br/>
<form method="get" action="/edit">
<input type="submit" value="Edit" />
<input type="hidden" name="id" value="<%=note.ts%>" />
</form>
</td>
</tr>
<% }); %>
</table>

addedit.html

<% include layout.html %>
<form method="post" action="<%=postpath%>">
<% if (note){ %>
<input type="hidden" name="id" value="<%=note.ts%>" />
<% } %>
<input type="text" name="author" value="<%=note.author%>" />
<br/>
<textarea rows="5" cols="40" name="note">
<%=note.note%>
</textarea>
<br/>
<input type="submit" value="Submit" />
</form>

login.html

<% include layout.html %>
<form method="POST" action="/login">
<p>Click the <i>Login</i> to log in.</p>
<input type="submit" value="Login" />
</form>

node setup.js

node app.js

从零开始学习Node.js例子八 使用SQLite3和MongoDB的更多相关文章

  1. 从零开始学习Node.js例子三 图片上传和显示

    index.js var server = require("./server"); var router = require("./router"); var ...

  2. 从零开始学习Node.js例子一 http get和post

    httpserverrequestget.js /* 获取GET请求内容 由于GET请求直接被嵌入在路径中,URL是完整的请求路径,包括了?后面的部分,因此你可以手动解析后面的内容作为GET请求的参数 ...

  3. 从零开始学习Node.js例子七 发送HTTP客户端请求并显示响应结果

    wget.js:发送HTTP客户端请求并显示响应的各种结果 options对象描述了将要发出的请求.data事件在数据到达时被触发,error事件在发生错误时被触发.HTTP请求中的数据格式通过MIM ...

  4. 从零开始学习Node.js例子六 EventEmitter发送和接收事件

    pulser.js /* EventEmitter发送和接收事件 HTTPServer和HTTPClient类,它们都继承自EventEmitter EventEmitter被定义在Node的事件(e ...

  5. 从零开始学习Node.js例子九 设置HTTP头

    server.js //basic server的配置文件 ; var server = require('./basicserver').createServer(); server.useFavI ...

  6. 从零开始学习Node.js例子五 服务器监听

    httpsnifferInvoke.js var http = require('http'); var sniffer = require('./httpsniffer'); var server ...

  7. 从零开始学习Node.js例子四 多页面实现数学运算 续二(client端和server端)

    1.server端 支持数学运算的服务器,服务器的返回结果用json对象表示. math-server.js //通过监听3000端口使其作为Math Wizard的后台程序 var math = r ...

  8. 从零开始学习Node.js例子四 多页面实现数学运算 续一(使用connect和express框架)

    1.使用connect框架 .use方法用于绑定中间件到connect服务器,它会配置一系列在接到请求时调用的中间件模块,此例中我们要配置的中间件有favicon logger static rout ...

  9. 从零开始学习Node.js例子四 多页面实现数学运算

    app-node.js ; var http = require('http'); var htutil = require('./htutil'); var server = http.create ...

随机推荐

  1. Git bash使用中...

    理解Head指向分支及标签tag Head指向当前分支(如master),可以把每次提交完成的修改看成一个圈,在修改上可以开另一分支为接下来的修改做准备,未修改前新建的分支与当前分支可看成绕修改圈转: ...

  2. 基于PNotify的消息提示Demo(轮询)

    需求:有些任务需要定时更新,获取最新的消息,这样就需要定时轮询,再者需要一种友好的提示. 以下就是使用PNotify插件的消息提示: 1.HTML代码 <!DOCTYPE html> &l ...

  3. [原创]Win7、Win8、Win10始终以管理员身份运行程序。

    在Win7.Win8.Win10系统中,以管理员身份运行程序很麻烦,一般有以下几种方式: 1.在可执行程序或快捷方式上右键,以管理员身份运行: 2.在可执行程序或快捷方式上右键->属性-> ...

  4. MHA+Atlas+mysql一主一从开启gtid安装配置与实验

    各节点架构 (说明:生产环境有两个节点可以组成一套完整集群,我是测试环境,因此对于manager以及atlas和binlog server都是单点,如果生产环境,相应的将manager以及atlas和 ...

  5. <java基础学习>02JAVA的基础组成

    Java的基础组成 1 关键字 (被赋予了特殊含义的单词) 2 标识符 3 注释 4 常量和变量 5 运算符 6 语句 7 函数 8 数组 关键字 class Demo{ public static ...

  6. 《AngularJS权威教程》中关于指令双向数据绑定的理解

    在<AngularJS权威教程>中,自定义指令和DOM双向数据绑定有一个在线demo,网址:http://jsbin.com/IteNita/1/edit?html,js,output,具 ...

  7. (BFS)poj3669-Meteor Shower

    题目地址 为判断某时刻能否走到某位置,建立shi数组,记录某位置最早t时刻就不能走.(初始化为-1)之后开始从(0,0)出发bfs,用bu数组记录走到某一位置时花费的步数,并且需要用vi数组记录是否走 ...

  8. 转-httpd 2.4.4 + mysql-5.5.28 + php-5.4.13编译安装过程

    一.编译安装apache 1.解决依赖关系 httpd-2.4.4需要较新版本的apr和apr-util,因此需要事先对其进行升级.升级方式有两种,一种是通过源代码编译安装,一种是直接升级rpm包.这 ...

  9. 浅谈sizeof

    问题:1)sizeof是函数吗:2)sizeof功能:3)具体问题下sizeof值 1)sizeof不是函数,是C语言的一个关键字 2)sizeof作为右值时,求①某个数据类型(sizeof(int) ...

  10. 【转】 Easy RadControl 之 RadGridView(Silverlight)

    1.不显示第1列即列指示器(Row Indicators) 在 telerik:RadGridView中设置属性   RowIndicatorVisibility="Collapsed&qu ...