从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析


Posted in Javascript onApril 13, 2017

本文实例讲述了Node.js中SQLite3和MongoDB的用法。分享给大家供大家参考,具体如下:

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下安装部署 :https://3water.com/article/111112.htm

安装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(3000);

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用法分析

从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析

从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析

从零开始学习Node.js系列教程之SQLite3和MongoDB用法分析

希望本文所述对大家nodejs程序设计有所帮助。

Javascript 相关文章推荐
使用jQuery.Validate进行客户端验证(初级篇) 不使用微软验证控件的理由
Jun 28 Javascript
为JavaScript添加重载函数的辅助方法
Jul 04 Javascript
ExtJS4 Grid改变单元格背景颜色及Column render学习
Feb 06 Javascript
webapp框架AngularUI的demo改造之路
Dec 21 Javascript
jquery实现翻动fadeIn显示的方法
Mar 05 Javascript
jQuery构造函数init参数分析
May 13 Javascript
使用impress.js制作幻灯片
Sep 09 Javascript
jquery实现二级导航下拉菜单效果
Dec 18 Javascript
jQuery Ajax 实例代码 ($.ajax、$.post、$.get)
Apr 29 Javascript
微信小程序实现两边小中间大的轮播效果的示例代码
Dec 07 Javascript
浅谈vuex为什么不建议在action中修改state
Feb 02 Javascript
Selenium执行Javascript脚本参数及返回值过程详解
Apr 01 Javascript
JS 插件dropload下拉刷新、上拉加载使用小结
Apr 13 #Javascript
angularjs指令之绑定策略(@、=、&amp;)
Apr 13 #Javascript
从零开始学习Node.js系列教程六:EventEmitter发送和接收事件的方法示例
Apr 13 #Javascript
详解angularJs指令的3种绑定策略
Apr 13 #Javascript
vue2实现移动端上传、预览、压缩图片解决拍照旋转问题
Apr 13 #Javascript
Vue组件tree实现树形菜单
Apr 13 #Javascript
从零开始学习Node.js系列教程五:服务器监听方法示例
Apr 13 #Javascript
You might like
PHP扩展模块memcached长连接使用方法分析
2014/12/24 PHP
PHP也能干大事 随机函数
2015/04/14 PHP
教你在PHPStorm中配置Xdebug
2015/07/27 PHP
php输出含有“#”字符串的方法
2017/01/18 PHP
thinkPHP5框架实现基于ajax的分页功能示例
2018/06/12 PHP
Laravel 5.1 框架Blade模板引擎用法实例分析
2020/01/04 PHP
jquery 如何动态添加、删除class样式方法介绍
2012/11/07 Javascript
js Map List 遍历使用示例
2013/07/10 Javascript
jquery实现个人中心导航菜单效果和美观都非常不错
2014/09/02 Javascript
Javascript中的几种URL编码方法比较
2015/01/23 Javascript
JQuery CheckBox(复选框)操作方法汇总
2015/04/15 Javascript
javascript数据类型验证方法
2015/12/31 Javascript
使用javascript插入样式
2016/03/14 Javascript
微信小程序  action-sheet详解及实例代码
2016/11/09 Javascript
Javascript 两种刷新方法以及区别和适用范围
2017/01/17 Javascript
微信小程序 request接口的封装实例代码
2017/04/26 Javascript
JavaScript实现修改伪类样式
2017/11/27 Javascript
javascript代码优化的8点总结
2018/01/29 Javascript
angular项目中bootstrap-datetimepicker时间插件的使用示例
2018/03/15 Javascript
Js通过AES加密后PHP用Openssl解密的方法
2019/07/12 Javascript
Vue实现回到顶部和底部动画效果
2019/07/31 Javascript
python网络编程学习笔记(五):socket的一些补充
2014/06/09 Python
python实现自动网页截图并裁剪图片
2018/07/30 Python
局域网内python socket实现windows与linux间的消息传送
2019/04/19 Python
CSS3 中filter(滤镜)属性使用详解
2020/04/07 HTML / CSS
三星俄罗斯授权在线商店:Samsung俄罗斯
2019/09/28 全球购物
什么是数据库锁?Oracle中都有哪些类型的锁?
2015/08/21 面试题
英文导游欢迎词
2014/01/11 职场文书
初中班主任寄语
2014/04/04 职场文书
学雷锋志愿者活动方案
2014/08/21 职场文书
求职意向书范本
2015/05/11 职场文书
民间借贷纠纷答辩状
2015/08/03 职场文书
2015年学校消防安全工作总结
2015/10/14 职场文书
管理者日常工作必备:22条企业管理流程模板!
2019/07/12 职场文书
使用Python解决图表与画布的间距问题
2022/04/11 Python
java版 联机五子棋游戏
2022/05/04 Java/Android