从零开始学习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实现简单时尚快捷的气泡提示插件
Dec 20 Javascript
js获取input标签的输入值实现代码
Aug 05 Javascript
使用JavaScript实现Java的List功能(实例讲解)
Nov 07 Javascript
jquery判断小数点两位和自动删除小数两位后的数字
Mar 19 Javascript
IE6-IE9中tbody的innerHTML不能赋值的解决方法
Sep 26 Javascript
JS实现同一个网页布局滑动门和TAB选项卡实例
Sep 23 Javascript
第五章之BootStrap 栅格系统
Apr 25 Javascript
JS根据生日月份和日期计算星座的简单实现方法
Nov 24 Javascript
解析利用javascript如何判断一个数为素数
Dec 08 Javascript
JS实现字符串去重及数组去重的方法示例
Apr 21 Javascript
小程序实现横向滑动日历效果
Oct 21 Javascript
vue实现在线预览pdf文件和下载(pdf.js)
Nov 26 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和JavaScript判断请求是否来自微信内浏览器
2015/08/18 PHP
PHP编程基本语法快速入门手册
2016/01/07 PHP
golang实现php里的serialize()和unserialize()序列和反序列方法详解
2018/10/30 PHP
php中array_fill函数的实例用法
2021/03/02 PHP
JavaScript Base64编码和解码,实现URL参数传递。
2006/09/18 Javascript
ExtJS下grid的一些属性说明
2009/12/13 Javascript
javascript实现当前页导航激活的方法
2015/02/27 Javascript
JavaScript使用cookie实现记住账号密码功能
2015/04/27 Javascript
javascript实现链接单选效果的方法
2015/05/13 Javascript
Webpack 实现 Node.js 代码热替换
2015/10/22 Javascript
轻松实现javascript图片轮播特效
2016/01/13 Javascript
获取input标签的所有属性的方法
2016/06/28 Javascript
leaflet的开发入门教程
2016/11/17 Javascript
理解AngularJs篇:30分钟快速掌握AngularJs
2016/12/23 Javascript
基于Vuejs和Element的注册插件的编写方法
2017/07/03 Javascript
原生js实现拖拽移动与缩放效果
2020/08/24 Javascript
vue-resource 拦截器interceptors使用详解
2021/01/18 Vue.js
[04:03]2014DOTA2西雅图国际邀请赛 LGD战队巡礼
2014/07/07 DOTA
win7安装python生成随机数代码分享
2013/12/27 Python
Linux系统上Nginx+Python的web.py与Django框架环境
2015/12/25 Python
Python使用Tkinter实现机器人走迷宫
2018/01/22 Python
Django项目开发中cookies和session的常用操作分析
2018/07/03 Python
Python参数类型以及常见的坑详解
2019/07/08 Python
解决win7操作系统Python3.7.1安装后启动提示缺少.dll文件问题
2019/07/15 Python
Python实现RGB与HSI颜色空间的互换方式
2019/11/27 Python
Python利用全连接神经网络求解MNIST问题详解
2020/01/14 Python
详解django使用include无法跳转的解决方法
2020/03/19 Python
CSS3 3D立方体效果示例-transform也不过如此
2016/12/05 HTML / CSS
Css3新特性应用之形状总结
2016/12/08 HTML / CSS
Mybag美国/加拿大:英国奢华包包和名牌手袋网站
2020/02/16 全球购物
Java里面有没有全局变量?为什么?
2015/02/06 面试题
简述索引存取方法的作用和建立索引的原则
2013/03/26 面试题
征兵宣传标语
2014/06/20 职场文书
安全保卫工作竞聘材料
2014/08/25 职场文书
盗窃案辩护词
2015/05/21 职场文书
冰雪公主观后感
2015/06/16 职场文书