从零开始学习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 相关文章推荐
jQueryUI如何自定义组件实现代码
Nov 14 Javascript
Array的push与unshift方法性能比较分析
Mar 05 Javascript
js判断样式className同时增加class或删除class
Jan 30 Javascript
FF IE浏览器修改标签透明度的方法
Jan 27 Javascript
javascript实现通过表格绘制颜色填充矩形的方法
Apr 21 Javascript
JS实现网站菜单拖拽移位效果的方法
Sep 24 Javascript
理解JS绑定事件
Jan 19 Javascript
JavaScript操作选择对象的简单实例
May 16 Javascript
利用css+原生js制作简单的钟表
Apr 07 Javascript
详解Node项目部署到云服务器上
Jul 12 Javascript
详解vue中使用express+fetch获取本地json文件
Oct 10 Javascript
js常见遍历操作小结
Jun 06 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自动获取字符串编码函数mb_detect_encoding
2011/05/31 PHP
php对包含html标签的字符串进行截取的函数分享
2014/06/19 PHP
php通过文件流方式复制文件的方法
2015/03/13 PHP
thinkphp3.2中Lite文件替换框架入口文件或应用入口文件的方法
2015/05/21 PHP
使用PHP+MySql+Ajax+jQuery实现省市区三级联动功能示例
2017/09/15 PHP
PHP array_reduce()函数的应用解析
2018/10/28 PHP
jquery及原生js获取select下拉框选中的值示例
2013/10/25 Javascript
Jquery简单分页实现方法
2015/07/24 Javascript
分享网页检测摇一摇实例代码
2016/01/14 Javascript
BootStrap selectpicker
2016/06/20 Javascript
bootstrap 表单验证使用方法
2017/01/11 Javascript
jQuery简单实现MD5加密的方法
2017/03/03 Javascript
详解用Node.js实现Restful风格webservice
2017/09/29 Javascript
ES6使用新特性Proxy实现的数据绑定功能实例
2020/05/11 Javascript
Python 第一步 hello world
2009/09/25 Python
python中返回矩阵的行列方法
2018/04/04 Python
Python操作配置文件ini的三种方法讲解
2019/02/22 Python
详解Python 定时框架 Apscheduler原理及安装过程
2019/06/14 Python
Django的用户模块与权限系统的示例代码
2019/07/24 Python
python dumps和loads区别详解
2020/02/04 Python
在python image 中实现安装中文字体
2020/05/16 Python
python获取系统内存占用信息的实例方法
2020/07/17 Python
咖啡为什么会有酸味?你喝到的咖啡為什麼是酸的?
2021/03/17 冲泡冲煮
CSS3实现DIV圆角效果完整代码
2012/10/10 HTML / CSS
HTML5 Web存储方式的localStorage和sessionStorage进行数据本地存储案例应用
2012/12/09 HTML / CSS
俄罗斯最大的香水和化妆品网上商店:Randewoo
2020/11/05 全球购物
类如何去实现接口
2013/12/19 面试题
大学生创业计划书的用途
2014/01/08 职场文书
家长给孩子的表扬信
2014/01/17 职场文书
课改先进个人汇报材料
2014/01/26 职场文书
销售员个人求职的自我评价
2014/02/10 职场文书
公务员政审材料范文
2014/12/23 职场文书
《秋思》教学反思
2016/02/23 职场文书
手把手教你用SpringBoot将文件打包成zip存放或导出
2021/06/11 Java/Android
Windows环境下实现批量执行Sql文件
2021/10/05 SQL Server
SpringBoot系列之MongoDB Aggregations用法详解
2022/02/12 MongoDB