从零开始学习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 相关文章推荐
图片格式的JavaScript和CSS速查手册
Aug 20 Javascript
js取整数、取余数的方法
May 11 Javascript
jquery实现二级导航下拉菜单效果
Dec 18 Javascript
分享JS数组求和与求最大值的方法
Aug 11 Javascript
Vuejs第九篇之组件作用域及props数据传递实例详解
Sep 05 Javascript
angular指令笔记ng-options的使用方法
Sep 18 Javascript
jquery ztree实现右键收藏功能
Nov 20 jQuery
Vue + Vue-router 同名路由切换数据不更新的方法
Nov 20 Javascript
JavaScript中使用import 和require打包后实现原理分析
Mar 07 Javascript
jQuery基于Ajax实现读取XML数据功能示例
May 31 jQuery
vue路由 遍历生成复数router-link的例子
Oct 30 Javascript
解决vux 中popup 组件Mask 遮罩在最上层的问题
Nov 03 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开发中常用的字符串操作函数
2011/02/08 PHP
php面向对象 字段的声明与使用
2012/06/14 PHP
PHP jpgraph库的配置及生成统计图表:折线图、柱状图、饼状图
2017/05/15 PHP
php实现生成带二维码图片并强制下载功能
2018/02/24 PHP
Thinkphp 框架扩展之应用模式实现方法分析
2020/04/27 PHP
window.location和document.location的区别分析
2008/12/23 Javascript
jquery配合css简单实现返回顶部效果
2013/09/30 Javascript
返回顶部按钮响应滚动且动态显示与隐藏
2014/10/14 Javascript
js中iframe调用父页面的方法
2014/10/30 Javascript
JavaScript学习笔记之数组去重
2016/03/23 Javascript
原生JS实现几个常用DOM操作API实例
2017/01/19 Javascript
Node.js实现文件上传的示例
2017/06/28 Javascript
jQuery实现的简单手风琴效果示例
2018/08/29 jQuery
[34:10]Secret vs VG 2019国际邀请赛淘汰赛 败者组 BO3 第二场 8.24
2019/09/10 DOTA
用python代码做configure文件
2014/07/20 Python
python执行get提交的方法
2015/04/29 Python
python实现的简单FTP上传下载文件实例
2015/06/30 Python
python选择排序算法实例总结
2015/07/01 Python
详解Python中表达式i += x与i = i + x是否等价
2017/02/08 Python
在pycharm中设置显示行数的方法
2019/01/16 Python
Python ArgumentParse的subparser用法说明
2020/04/20 Python
python实现在内存中读写str和二进制数据代码
2020/04/24 Python
解决django框架model中外键不落实到数据库问题
2020/05/20 Python
在keras中model.fit_generator()和model.fit()的区别说明
2020/06/17 Python
Python爬虫之Selenium实现窗口截图
2020/12/04 Python
使用css3实现的tab选项卡代码分享
2014/12/09 HTML / CSS
英国Amara家居法国网站:家居装饰,现代装饰和豪华礼品
2016/12/15 全球购物
Sneaker Studio乌克兰:购买运动鞋
2018/03/26 全球购物
Java的接口和C++的虚类的相同和不同处
2014/03/27 面试题
岗位职责的含义
2013/11/17 职场文书
幼儿园春游活动方案
2014/01/19 职场文书
《数星星的孩子》教学反思
2014/04/11 职场文书
幼儿教师师德承诺书
2014/05/23 职场文书
千手观音观后感
2015/06/03 职场文书
手把手教你从零开始react+antd搭建项目
2021/06/03 Javascript
Redisson实现Redis分布式锁的几种方式
2021/08/07 Redis