准备

在上一篇的基础上,通过npm安装mongoose。

关于mongoose

Mongoose是MongoDB的一个对象模型工具,是基于node-mongodb-native开发的MongoDB nodejs驱动,可以在异步的环境下执行。同时它也是针对MongoDB操作的一个对象模型库,封装了MongoDB对文档的的一些增删改查等常用方法,让NodeJS操作Mongodb数据库变得更加灵活简单。

Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力
Model : 由Schema发布生成的模型,具有抽象属性和行为的数据库操作对
Entity : 由Model创建的实体,他的操作也会影响数据库

它们之间的关系是Schema生成Model,Model创造Entity,Model和Entity都可对数据库操作造成影响,但Model比Entity更具操作性。Model对应collection,Entity对应docment。

Mongoose API:http://mongoosejs.com/docs/api.html

CRUD操作

1.增加

如果是Entity,使用save方法,如果是Model,使用create方法

// mongoose 链接
var mongoose = require('mongoose');
var db       = mongoose.connect('mongodb://127.0.0.1:27017/chm');
// 链接错误
db.connection.on('error', function(error) {console.log(error);
});db.connection.on("open", function () {
console.log("——数据库连接成功!——");
});// Schema 结构
var vipSchema = new mongoose.Schema({name : {type : String, default : 'java'},addr    : {type : String},addTime  : {type : Date, default: Date.now},age      : {type : Number}
});
//中间件
//save之前触发
vipSchema.pre('save', function(next){console.log("pre save");next();
});
vipSchema.post('save', function (doc) {//doc是当前插入的文档console.log(doc);
});// model
var vipModel = db.model('vip', vipSchema);
// 增加记录 基于 entity 操作
var doc = {name : 'java', age:20, addr:"shanghai"};
var vipEntity= new vipModel(doc);vipEntity.save(function(error) {if(error) {console.log(error);} else {console.log('saved OK!');}// 关闭数据库链接db.disconnect();
});
//增加记录 基于model操作
vipModel.create(doc, function(error){if(error) {console.log(error);} else {console.log('save ok');}// 关闭数据库链接db.disconnect();
});

这里有个问题,当执行完上面的代码后,到数据库中执行db.vip.find();命令你会发现查不到刚添加的那条数据,再执行show collections你会发现多了一个vips集合,数据在这个集合里面。这里Mongoose在模型名至数据库集合名的命名转换上做了文章,下面会介绍。
2.查找

var mongoose = require("mongoose");
var db = mongoose.connect('mongodb://localhost:27017/chm'); db.connection.on("error", function (error) {
console.log("数据库连接失败:" + error);
});
db.connection.on("open", function () {
console.log("——数据库连接成功!——");
});var Schema = mongoose.Schema;
//模板
var vipSchema = new Schema({name:String,age:Number,addr:String,addTime:Date
});// 添加 mongoose 实例方法
vipSchema.methods.findByName = function(hello, callback) {return this.model('vips').find({name: hello}, callback);
}
// 添加 mongoose 静态方法,静态方法在Model层就能使用
vipSchema.statics.findbyage = function(age, callback) {return this.model('vips').find({age: age}, callback);
}//模型
var vipModel = mongoose.model('vips', vipSchema);vipModel.find({name:"java"},function(error, result){if(error) {console.log(error);} else {console.log(result);}//关闭数据库链接db.disconnect();});
//基于实例方法的查询
var entity = new vipModel({"name":"java"});
entity.findByName("java",function(error, result){if(error) {console.log(error);} else {console.log(result);}//关闭数据库链接db.disconnect();
});//基于静态方法的查询
vipModel.findbyage(20, function(error, result){if(error) {console.log(error);} else {console.log(result);}//关闭数据库链接db.disconnect();;
});

另一种查询:查询时不带回调

vipModel.find({ occupation: /host/ }).where('name.last').equals('Ghost').where('age').gt(17).lt(66).where('likes').in(['vaporizing', 'talking']).limit(10).sort('-occupation').select('name occupation').exec(callback);

如果不带callback,则返回query,query没有执行的预编译查询语句,该query对象执行的方法都将返回自己,只有在执行exec方法时才执行查询,而且必须有回调。

3.修改

//省略上面相同代码
......// 修改记录
var conditions = {name : 'java'};
var update     = {$set : {age : 27}};
var options    = {upsert : true};
vipModel.update(conditions, update, options, function(error){if(error) {console.log(error);} else {console.log('update ok!');}//关闭数据库链接db.disconnect();
});

4.删除

删除有2种方式,Entity和Model都使用remove方法

//省略上面相同代码
......var conditions = {username: 'java'};
vipModel.remove(conditions, function(error){if(error) {console.log(error);} else {console.log('delete ok!');}//关闭数据库链接db.disconnect();
});

Sub Docs

如同SQL数据库中2张表有主外关系,Mongoose将2个Document的嵌套叫做Sub-Docs(子文档)

简单的说就是一个Document嵌套另外一个Document或者Documents:

var ChildSchema1 = new Schema({name:String});
var ChildSchema2 = new Schema({name:String});
var ParentSchema = new Schema({children1:ChildSchema1,   //嵌套Documentchildren2:[ChildSchema2]  //嵌套Documents
});

Sub-Docs享受和Documents一样的操作,但是Sub-Docs的操作都由父类去执行

var ParentModel = db.model('Parent',parentSchema);var parent = new ParentModel({children2:[{name:'c1'},{name:'c2'}]});parent.children2[0].name = 'd';parent.save(callback);

parent在执行保存时,由于包含children2,他是一个数据库模型对象,因此会先保存chilren2[0]和chilren2[1]。

如果子文档在更新时出现错误,将直接报在父类文档中,可以这样处理:

ChildrenSchema.pre('save',function(next){if('x' === this.name) return next(new Error('#err:not-x'));next();});var parent = new ParentModel({children1:{name:'not-x'}});parent.save(function(err){console.log(err.message); //#err:not-x});

4.1 查询子文档

如果children是parent的子文档,可以通过如下方法查询到children

var child = parent.children.id(id);

4.2 新增、删除、更新

子文档是父文档的一个属性,因此按照属性的操作即可,不同的是在新增父类的时候,子文档是会被先加入进去的。

如果ChildrenSchema是临时的一个子文档,不作为数据库映射集合,可以这样:

var ParentSchema = new Schema({children:{name:String}
});
//其实就是匿名混合模式

数据验证

数据的存储是需要验证的,不是什么数据都能往数据库里丢或者显示到客户端的,数据的验证需要记住以下规则:

  • 验证始终定义在SchemaType中
  • 验证是一个内部中间件
  • 验证是在一个Document被保存时默认启用的,除非你关闭验证
  • 验证是异步递归的,如果你的SubDoc验证失败,Document也将无法保存
  • 验证并不关心错误类型,而通过ValidationError这个对象可以访问
    7.1 验证器
  • required 非空验证
  • min/max 范围验证(边值验证)
  • enum/match 枚举验证/匹配验证
  • validate 自定义验证规则

以下是综合案例:

    var PersonSchema = new Schema({name:{type:'String',required:true //姓名非空},age:{type:'Nunmer',min:18,       //年龄最小18max:120     //年龄最大120},city:{type:'String',enum:['北京','上海']  //只能是北京、上海人},other:{type:'String',validate:[validator,err]  //validator是一个验证函数,err是验证失败的错误信息}});

7.2 验证失败

如果验证失败,则会返回err信息,err是一个对象该对象属性如下

err.errors                //错误集合(对象)
err.errors.color          //错误属性(Schema的color属性)
err.errors.color.message  //错误属性信息
err.errors.path             //错误属性路径
err.errors.type             //错误类型
err.name                //错误名称
err.message                 //错误消息

一旦验证失败,Model和Entity都将具有和err一样的errors属性。

Model至Collection的命名策略

mongoose/lib/util.js模块中如下代码片段是集合命名的根源。

function pluralize (str) {var rule, found;if (!~uncountables.indexOf(str.toLowerCase())){found = rules.filter(function(rule){return str.match(rule[0]);});if (found[0]) return str.replace(found[0][0], found[0][1]);}return str;
};

1.判断模型名是否是不可数的,如果是直接返回模型名;否则进行复数转化正则匹配;

2.返回复数转化正则匹配结果(一个复数转化正则匹配是一个数组,有两个对象,[0]正则表达式,[1]匹配后处理结果);

3.如果复数转化正则匹配结果不存在,直接返回模型名;否则取匹配结果第一个,对模型名进行处理。(需要说明的是,rules是按特殊到一般的顺序排列的)

部分内容来自:http://ourjs.com/detail/53ad24edb984bb4659000013

nodejs操作mongodb数据库(mongoose)相关推荐

  1. Nodejs 操作 MongoDb 数据库

    一.在 Nodejs 中使用 Mongodb 在前面的博文我们给大家讲了如何使用命令操作 Mongodb,这篇博文开始我们给大家讲解一 下如何使用 Nodejs 来操作 Mongodb 数据库 Nod ...

  2. nodejs操作mongodb数据库

    安装mongoose npm install mongoose 连接数据库 var mongoose = require("mongoose");//27017mongodb默认端 ...

  3. 操作Mongodb数据库及性能测试

    文章目录 操作Mongodb数据库,性能测试 引入mongodb模板 开启mongodb数据库 连接mongodb数据库 插入一条数据 查询全部数据 测试性能 操作Mongodb数据库,性能测试 目标 ...

  4. 使用mongoose 在 Node中操作MongoDB数据库

    MongoDB 关系型和非关系型数据库 关系型数据库(表就是关系,或者说表与表之间存在关系). 所有的关系型数据库都需要通过sql语言来操作 所有的关系型数据库在操作之前都需要设计表结构 而且数据表还 ...

  5. 使用第三方包mongoose来操作MongoDB数据库,解决报错:MongooseError

    使用第三方包mongoose来操作MongoDB数据库 官方网站 配置文件 异常 异常描述: MongooseError: Operation cats.insertOne() buffering t ...

  6. node用mongodb还是mysql,Node 操作 mongoDB 数据库和 mySQL数据库

    下载安装 MongoDB image.png 直接点击下载就行了 image.png 安装 mongodb 一直点击下一步,知道这一步 image.png 选中自己选择想安装的目录路径(选择安装的目录 ...

  7. 58 Node.js中操作mongoDB数据库

    技术交流 QQ 群:1027579432,欢迎你的加入! 欢迎关注我的微信公众号:CurryCoder 的程序人生 1.数据库概述及环境搭建 1.1 为什么要使用数据库 动态网站中的数据都是存储在数据 ...

  8. eggjs使用egg-mongoose操作MongoDB数据库

    eggjs使用egg-mongoose操作MongoDB数据库 npm安装mongoose依赖 npm install egg-mongoose --save 配置config/plugin.js和c ...

  9. Python 操作 MongoDB 数据库!

    作者 |黄伟呢 来源 |数据分析与统计学之美 MongoDB是一个介于关系数据库和非关系数据库之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的. 先来看看MySQL与MongoDB 概念区别 ...

最新文章

  1. ajax 加载 提示 锁屏,js锁屏解屏通过对$.ajax进行封装实现
  2. [译文]Domain Driven Design Reference(五)—— 为战略设计的上下文映
  3. arm poky linux,Solved: Re: arm-poky-linux - NXP Community
  4. jsp 之 入门 jsp代码块
  5. python爬虫 爬取视频 练习
  6. Pycharm安装第三方包报错怎么办
  7. 英国某电商在线零售客户细分_Kaggle项目
  8. godaddy 服务器位置,GoDaddy DNS服务器地址 | Godaddy美国主机中文指南
  9. 平面三角形与三角函数(1):角的度量与换算、三角函数的定义、图形与特征
  10. 【机器学习 - 8】:随机梯度下降法
  11. centos图形化磁盘文件管理_centos7图形化分区和ks文件分区的配置
  12. Hello World生成
  13. 前端综合面试题一(持续更新)
  14. p2p 文件服务器集群,基于云计算的P2P流媒体服务器集群部署算法.doc
  15. 企业网络安全|监控解决方案
  16. 北邮在线计算机,北邮在线圆我IT梦
  17. json数据导出到excel中
  18. python mypy类型检查_Python 类型检查
  19. 2012-2020年全国大学生数学建模竞赛的国家一等奖论文
  20. 古诗词html,意境唯美的古诗词完整 让人美的心醉的诗词

热门文章

  1. php结课报告总结,课程总结以及笔记整理
  2. java typeof_typeof和instanceof的区别
  3. 敏捷是项目管理+合作
  4. position:sticky介绍
  5. 虹科为您介绍如何实现多相机同步技术
  6. 【程序人生】比悲伤更悲伤的故事
  7. windows系统socket泄露问题解决--No buffer space available (maximum connections reached?): JVM_Bind
  8. xsl php,XSL是什么以及有什么用
  9. 上交所前总工程师白硕:Libra招招制敌,中国是全球唯一有能力的应对者(全文)...
  10. Convolutional Networks for Voting-based Anomaly Classification in Metal Surface Inspection-论文阅读笔记