上一篇介绍了如何用express搭建起服务端MVC的开发架构,本篇我们来详细介绍一下这个Model层,也就是数据库访问层。包含如何使用mongodb搭建数据库,以及如何使用mongoose来访问数据。
 

mongodb的安装和启动

首先我们得安装mongodb,先去官网( http://www.mongodb.org/downloads)下载安装包,我的开发环境是Windows,所以下载Windows下的iso文件,根据提示一路安装完毕即可,没什么需要特别选择的。
安装完后,为了能在cmd中全局都能启动mongodb,我们需要配置环境变量,将安装目录下的bin目录配置在系统变量中,如图:
接下来,新建一个目录,用于存放数据库文件。我新建的目录为D:\mongodb\data\db,然后运行cmd,执行命令mongod --dbpath D:\mongodb\data\db,这个时候mongodb就运行起来了,我们就可以用程序来连接数据库了。
 

连接数据库

mongodb的默认端口是27017,我们在项目中有一个models文件夹,里面放置与数据库连接的数据模型,其中有一个mongodb.js,内容很简单:
var mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/QuestionMaker');
exports.mongoose = mongoose;
是标准的commonjs模块写法,先引用mongoose模块,然后连接数据库,对外暴露mongoose模块。可以看到我们在代码中去访问本地的QuestionMaker数据库。那么首先我们得有这个数据库才行。运行cmd,创建一个数据库
use QuestionMaker
db.createCollection("counters")
此命令会创建一个名为QuestionMaker的数据库,并在该库创建一个集合counters(这个集合我们后续会用到),必须得这么写,否则数据库无法创建。驱动模块写好了,我们在其他模块中引用该模块后,就可以连接到数据库了。
 

使用mongoose操作数据库

我们看到上面用了一个叫做mongoose的模块,它是一个nodejs模块,mongoose提供了Schema、Model、Documents对象,用它可以更加直观的操作数据库,所以很多人喜欢这个模块,我们项目中也用它来操作数据库。
为了能以我们熟悉的面向对象的方式来访问数据库,我们先根据试题的数据结构来创建一个Schema:
var QuestionSchema = new Schema({
id: String,
qtype: Number,
name: String,
content: String,
options: [
{
name: String
}
],
answer: String
});
Schema可以理解为一个模板,根据此模版,我们可以用mongoose.model来创建出一个Question类,代码如下:
var Question = mongodb.mongoose.model("Question", QuestionSchema);
利用Question类示例化出的对象带有很多方法用来访问/操作数据库,如save方法,可以保存一条文档,也就是document(mongodb中的概念,类似我们以前概念中的一条记录)。
为了尽可能少的对外暴露数据(封装性),我新建了一个QuestionDAO对象,也就是仿造java中的概念,加一个DAO层,用来提供数据访问。对外暴露的方法都定义在这个对象上,例如保存记录和更新记录的代码如下:
//保存试题
QuestionDAO.prototype.save = function(obj, callback){
var instance = new Question(obj);
instance.save(function(err){
callback(err, null);
});
} //更新试题
QuestionDAO.prototype.update = function(obj, callback){
Question.findByIdAndUpdate(obj._id, obj, {}, function(err){
callback(err, null);
});
}
用了mongoose提供的save方法和findByIdAndUpdate方法,每一个操作之后都可以传回调函数,这样我们就能把数据库访问的结果返回给controller层了。
另外,根据业务需求,我们就可以写更多的方法了,如项目中的list、get、remove,分别用来获取试题列表、获取试题、删除试题。其中list方法中还实现了分页返回数据。
 

mongodb实现id自增

id自增是数据库的一个常见需求,在mysql中,只要指定字段auto_increment即可,在mongodb中,没有这样的方法,所以必须得在代码中实现才行。我们按照官方给出的解决方法,实现questions集合的id自增。
id自增功能需要一个辅助的集合来完成,就是我们之前新建好的counters,用来记录当前的id值为多少。在mongodb命令行中执行db.counters.save({_id: "questionid", seq: 0})完成初始化。_id是mongodb默认提供的一个字段,我们这里赋值为questionid,是为了做一个标记,以便在后面能够查找出这条记录。
然后在question.js中创建CounterSchema并生成一个Counter类,用来操作counters集合,代码如下:
var CounterSchema = Schema({
_id: {type: String, required: true},
seq: { type: Number, default: 1 }
}); var Counter = mongodb.mongoose.model("Counter", CounterSchema);
然后,在QuestionSchema的save方法之前,我们应该先去counters中获取最新id,可以用pre方法来实现,代码如下:
QuestionSchema.pre('save', function(next) {
var doc = this;
Counter.findByIdAndUpdate({_id: 'questionid'}, {$inc: { seq: 1} }, function(error, counter) {
if(error)
return next(error);
doc.id = counter.seq;
next();
});
});
QuestionSchema.set('toObject', { getters: true });
如此一来,每次Question执行save方法的时候,都会调用这个函数,从而获取到递增后的最新id。
 

备份和导入

数据库的备份和导入当然是必不可少了,比如大家可以拿这我的备份文件直接导入来练习,这样就省去了一步一步创建的步骤。
备份数据库可以使用mongodump命令,用法如下:
mongodump -h dbhost -d dbname -o dbdirectory
导入已有的数据库可以使用mongostore命令,用法如下:
mongorestore -h dbhost -d dbname –directoryperdb dbdirectory
具体的参数可以在网上搜索,文章很多,此处不再详细说明。
 

客户端工具

mongodb有没有像mysql那样的客户端工具呢?当然有啦,我使用的是robomongo这个工具,简单好用,界面如下,大家可以尝试使用。
 
使用MEAN技术栈开发web应用系列三部曲就到这里了,再次附上练手项目的地址:https://github.com/Double-Lv/QuestionMaker
另外,本系列文章只是一个入门级别的介绍,所写的代码以及数据库的设计基本上都属于”玩具代码“,写一个自己玩的项目还行。在实际的项目中,我们还得考虑各种因素,性能、负载等等,更多话题有待研究。

用“MEAN”技术栈开发web应用(三)用mongodb搭建数据库的更多相关文章

  1. 用“MEAN”技术栈开发web应用(一)AngularJs前端架构

    前言 不知何时突然冒出“MEAN技术栈”这个新词,听起来很牛逼的样子,其实就是我们已经熟悉了的近两年在前端比较流行的技术,mongodb.express.angularjs.nodejs,由于这几项技 ...

  2. “MEAN”技术栈开发web应用

    “MEAN”技术栈开发web应用 上一篇我们讲了如何使用angular搭建起项目的前端框架,前端抽象出一个service层来向后端发送请求,后端则返回相应的json数据.本篇我们来介绍一下,如何在no ...

  3. 用“MEAN”技术栈开发web应用(二)express搭建服务端框架

    上一篇我们讲了如何使用angular搭建起项目的前端框架,前端抽象出一个service层来向后端发送请求,后端则返回相应的json数据.本篇我们来介绍一下,如何在nodejs环境下利用express来 ...

  4. Spring Security技术栈开发企业级认证与授权(一)环境搭建

    本项目是基于慕课网的Spring Security技术栈开发企业级认证与授权,采用IDEA开发,本文章用来记录该项目的学习过程. 慕课网视频:https://coding.imooc.com/clas ...

  5. Python全栈开发【基础三】

    Python全栈开发[基础三]  本节内容: 函数(全局与局部变量) 递归 内置函数 函数 一.定义和使用 函数最重要的是减少代码的重用性和增强代码可读性 def 函数名(参数): ... 函数体 . ...

  6. 基于.Net进行前端开发的技术栈发展路线(三)

    前言 上一篇<我的技能树二>文章分享了我的技能中的前端技能和Java技能,今天继续跟大家分享的就是后端技能了. 我的技能树 我当前的技能树: 其中,标注为黄色旗帜的是基本掌握,标注为红色旗 ...

  7. web技术栈开发原生应用-多端共用一套代码

    weex: vuejs开发原生应用 nativescript: vuejs开发原生应用 ReactNative = reactjs开发原生应用 ionic = angularjs 开发原生应用

  8. Python全栈开发-web框架之django

    一:web框架 什么是web框架? Web应用框架(Web application framework)是一种开发框架,用来支持动态网站.网络应用程序及网络服务的开发.这种框架有助于减轻网页开发时共通 ...

  9. CefSharp-基于C#的客户端开发框架技术栈开发全记录

    CefSharp简介 源于Google官方 CefSharp用途 CefSharp开发示例 CefSharp应用--弹窗与右键 不弹出子窗体 禁用右键 CefSharp应用--High DPI问题 缩 ...

随机推荐

  1. Arduino uno 引脚说明

    http://openhome.cc/Gossip/Books/mBlockArduino1-3and1-4.html http://swf.com.tw/?p=406

  2. jq冒泡之——点击其他地方隐藏

    e.stopPropagetion(); <!DOCTYPE html> <html lang="en"> <head> <meta ch ...

  3. Esri的开源JS项目杂谈

    一提到Esri大家首先想到的是庞大的ArcGIS产品大家族,其产品包含从桌面端,到服务器/云端,再到web/移动端.作为一名极客,不聊开源逼格似乎上不去啊.其实,Esri作为一个开放的平台,不仅有稳定 ...

  4. WebADNuke整理

    在webconfig上增添 <webadnuke> <database> <add name="SqlDbProvider" type="C ...

  5. 1.Linux中安装LNMP过程

    第一步安装mysql过程 安装包mysql-5.0.22.tar.gz,解压tar -zxvf  mysql-5.0.22.tar.gz cd mysql-5.0.22 进行源码安装./configu ...

  6. iOS 可执行文件瘦身方法

    编译选项 1.编译器优化级别 Build Settings->Optimization Level有几个编译优化选项,release版应该选择Fastest, Smalllest,这个选项会开启 ...

  7. C++-Qt【4】-CheckBox on QListView

    引用:http://www.qtcentre.org/threads/47119-checkbox-on-QListView QListWidgetItem *item = new QListWidg ...

  8. HDU4417 Super Mario(主席树)

    题目 Source http://acm.hdu.edu.cn/showproblem.php?pid=4417 Description Mario is world-famous plumber. ...

  9. 基于redis的点赞功能设计

    前言 点赞其实是一个很有意思的功能.基本的设计思路有大致两种, 一种自然是用mysql等 数据库直接落地存储, 另外一种就是利用点赞的业务特征来扔到redis(或memcache)中, 然后离线刷回m ...

  10. 阅读jquery源码与js依赖加载的模块化!

    阅读源码肯定是先下载有注释的源码 我也是醉了,10309 行代码,在陆续续的一个月之内,看完了,虽有收获但收获不大, 直到又一次看jquery的github,怎么会有cmd????没听过使用jquer ...