将js进行到底:node学习9
node.js数据库篇——Mongoose ODM
介绍mongoose
几乎所有的语言都有原生数据库连接驱动,这个我们上一回已经了解了,比如java的jdbc,mysql-connector,但是实际的开发中为了追求效率都不会使用原生的连接方式这么简单,至少我们也应该封装一个数据库连接文件,不应该每次操作都连接吧。为此,ORM,ODM诞生了,他们简化了数据库操作,将操作打包成简单的方法,并提供了数据的验证规则,安全保障等重要特性。
什么是ORM?
Object Relational Mapping缩写,是对象关系映射,面向对象语言的web开发中重要概念,产品上比如微软的ADO.NET的EntityFramework框架就是提供给ASP.NET开发的关系映射工具,还有笔者之前J2EE开发中SSH框架里的hibernate也是ORM产品,其实说白了就是将面向对象语言中的类(POJO类,那种只有属性和get,set的类)匹配到数据库的表,将实体化后的POJO对象匹配到数据库的一行数据,这样开发者只需要通过get,set对象里的属性,然后save,update一下,像hibernate这样的框架就自动使之对应到了数据库中的具体行,那么数据库就被修改了!这实现了强大的解耦合(开发语言中无需出现SQL语句),使开发者不必去做数据库管理员的事情(甚至不需要知道数据库语言),而专注于代码开发。ORM最大的缺点就是性能远远落后于原生SQL语句,因为像hibernate做的事情实际上就是封装了将对象映射为数据库的SQL语句罢了,永远是逃不过SQL语句操作数据库的。
什么是Mini ORM?
笔者接触mini orm是2015年在为自己创业公司开发ASP.NET平台接触到的,当时使用的产品是Petapoco。Mini orm的出现主要是弥补了ORM低性能的问题,可以理解为精简版的ORM,去除了一些复杂的映射方法,保留了基本的数据库操作方法,并且要求一些复杂的连接语句需要自己手动写SQL,也就是说开发时用基本方法+手动SQL混合式写法,这种ORM对开发者的要求要更高一些,但相比纯SQL还是要简单方便不少,可以说既保留了ORM的功能,同时提高了性能,介于SQL和ORM之间。
什么是ODM?
额,我也是第一次听说这个名词,Object Document Mapper的缩写,以前我只知道ORM,这里我探索了StackOverflow:
以上是别人询问ORM和ODM的区别的采纳回答,大意是:
mysql是关系型数据库,所以你需要用ORM工具将代码中的对象映射为数据库的数据
工具有:hibernate,entity framework,dapper等等
mongodb是文档类数据库,你需要用ODM来将你的代码中的对象翻译为数据库的数据。
mandango就是一个ODM工具
至于这个mandango ODM我看了下github官页说是专为php连接mongodb提供的ODM工具,就对应于node.js下的mongoose了。
什么是mongoose?
相比于原生的mongodb驱动器,mongoose做的第一件简化的事情就是假定了网站使用的是一个数据库,这在mysql中也是很常见的,我们一般一个网站只用一个库!这样整个应用只需要一次连接,处处可用,不必每次都去写连接方法!
然后,使用Mongoose无需担心数据库是否连接上了,他是先把数据库操作指令缓存起来,这就很像那些ORM产品一样,最后一次提交才算数,然后等到提交的时候一次连接数据库,将指令写入数据库。减少了连接次数,提高性能,简化操作验证。这样我们无需监听每一次的connection回掉函数了。
简单测试
package.json
{
"name":"mongoose-test",
"version":"0.0.1",
"description":"a mongoose example",
"dependencies":{
"mongoose":"latest"
}
}
查询数据
//引入mongoose模块
mongoose= require("mongoose");
//连接数据库,需要选择一个固定的库,之后不必再有连接操作
mongoose.connect('mongodb://localhost/test');
//定义模型样板
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var dataSchema = new Schema({
email:String,
password:String
});
//生成对象
//第一个参数就是集合名
var User = mongoose.model('User',dataSchema);
var name = {email:'devil'};
//根据name字段查询
User.find(name,function(err,data){
console.log(data);
console.log("\n")
});
var password = {password:'123456'};
//根据password字段查询
User.find(password,function(err,data){
console.log(data);
console.log("\n")
});
本次查询的数据就是上一章中构建的登录注册模块所使用的数据库集合User,第一次是查询email为“devil”的数据,第二次是查询密码为“123456”的数据。
新增数据
//引入mongoose模块
mongoose= require("mongoose");
//连接数据库,需要选择一个固定的库,之后不必再有连接操作
mongoose.connect('mongodb://localhost/test');
//定义模型样板
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var dataSchema = new Schema({
email:String,
password:String
});
//生成对象
//第一个参数就是集合名
var User = mongoose.model('User',dataSchema);
var save = {email:"devilyouwei@foxmail.com",password:"zzzz"};
var user = new User(save);//生成新对象,就是对应数据集合中一条新数据
//保存这个新对象,就是插入操作
user.save(function(err){
console.log("already saved");
})
本次操作通过模型的save方法存储了一行数据
更新操作
//引入mongoose模块
mongoose= require("mongoose");
//连接数据库,需要选择一个固定的库,之后不必再有连接操作
mongoose.connect('mongodb://localhost/test');
//定义模型样板
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var dataSchema = new Schema({
email:String,
password:String
});
//生成对象
//第一个参数就是集合名
var User = mongoose.model('User',dataSchema);
User.update({email:"devil"},{password:"hello"},function(err){
console.log("password already changed");
})
本次操作将email为“devil”的用户,密码修改为“hello”。
删除操作
//引入mongoose模块
mongoose= require("mongoose");
//连接数据库,需要选择一个固定的库,之后不必再有连接操作
mongoose.connect('mongodb://localhost/test');
//定义模型样板
var Schema = mongoose.Schema,
ObjectId = Schema.ObjectId;
var dataSchema = new Schema({
email:String,
password:String
});
//生成对象
//第一个参数就是集合名
var User = mongoose.model('User',dataSchema);
User.remove({email:"devilyouwei@gmail.com"},function(err){
console.log("devilyouwei@gmail.com already removed");
})
这里我们删除email为“devilyouwei@gmail.com”的数据
解析套路
使用mongoose对数据库进行增删改查的基本套路是:
- require mongoose模块进来,返回mongoose对象
- 使用mongoose对象connect进行连接操作,参数为连接套接字默认是:mongodb://localhost/数据库
- 定义模型样本——schema
- 根据schema获得对应集合的model,这一步很关键,获得了模型
- 使用find,remove,save,update对数据库进行基本操作
注意1
注:其中的save方法需要单独解释,我们发现,除了save其他三个没有new Model()操作,也就是不需要生成对象,使用的是静态方法(java中称类方法),比如find:
//生成对象
//第一个参数就是集合名
var User = mongoose.model('User',dataSchema);
var name = {email:'devil'};
//根据name字段查询
User.find(name,function(err,data){
console.log(data);
console.log("\n")
});
因为他们(find,remove,update)都是对集合中已经有的数据进行改删查操作,唯独,save是新增操作,必须生成新的对象,故而,save方法是基于新对象下的方法,需要new对象这一步操作:
var save = {email:"devilyouwei@foxmail.com",password:"zzzz"};
var user = new User(save); //重点:生成新对象,就是对应数据集合中一条新数据
//保存这个新对象,就是插入操作
user.save(function(err){
console.log("already saved");
})
注意到上述代码使用了new 模型这种骚操作,并设置的对应属性,这有点像java hibernate下的new对象然后使用set方法,或者直接构造方法传入数据,最后save一下就保存到数据库的操作,ODM和ORM的基本操作十分类似,可以说ODM是专为mongo这样的数据库而生的“特殊ORM”。
注意2
关于schema是个什么?
记住,他并不是模型,要理解schema,可以把它想象成模型的原型(js中叫做prototype),就是model的model(模型的模板),这个schema应当和数据库集合的属性一一对应,集合(表)中有name,那么schema在规定的时候就要有name,否则回误以为是新的集合或者报错。schema用于描述模型的样子以及模型是如何工作的,数据库的操作是发生在模型上的而不是schema上的。
注意3
关于model与数据库集合的对应关系。
首先要获得model,需要通过mongoose.model方法,并且传入集合名,schema。例如:
var dataSchema = new Schema({
email:String,
password:String
});
var User = mongoose.model('User',dataSchema);
User就是一个模型,model方法传入第一个是模型名称,如果model方法没有第三个参数,那么默认第一个参数与数据库集合名对应,注意,默认指定会全部被转换为小写+复数形式,比如这里是User,数据库中的集合叫做users!
注意4
设定默认值,防止空字符串
var dataSchema = new Schema({
email:{type:String,default:"example@gmail.com"},
password:{type:String,default:"123456"}
});
更多常用操作方法
SQL语句丰富多彩,有很多关键词,where,limit,like等等。我以为mongodb不是关系数据库可能不存在或者不太一样,事实上mongoose也有这些关键词,并且是使用类似Thinkphp那样的链式操作。
使用链式操作查询数据
//引入mongoose模块
mongoose= require("mongoose");
//连接数据库,需要选择一个固定的库,之后不必再有连接操作
mongoose.connect('mongodb://localhost/test');
//定义模型样板
var Schema = mongoose.Schema;
var userSchema = new Schema({
email:String,
password:String
});
//生成对象
//第一个参数就是集合名
var User = mongoose.model('User',userSchema);
User.where('email').eq('devil').exec(function(err,data){
console.log(data);
});
前面的步骤都一样,只是利用了链式操作,把条件依次链接起来,最终使用exec执行整个链。
注意上述代码where和eq组合可以只用find代替:
var User = mongoose.model('User',userSchema);
User.find({email:"devil"},function(err,data){
console.log(data);
}
这段链更加简单,只需要一个find即可
一些常用的链式方法
链式操作的方法名和SQL语言的关键词很相似,基本就是同名同义了
大于小于
var data = User.where('email').gt(1).find(function(err,data){
console.log(data);
})
gt大于,lt小于,eq等于,neq不等于
注意:使用find,exec的效果测试下来效果一样
Like语句
var data = User.where('email').regex(/mail/).find(function(err,data){
console.log(data);
})
在mongoose中并没有找到Like关键词,要模糊查询需要用到正则表达式。regex方法里面可以输入正则表达式。
以上代码用于查找email中带有“mail”字样的行。
count计数
User.find({'email':/mail/}).count(function(err,data){
console.log(data);
})
统计带有“mail”的email的行数,在count中传入回掉函数即可
limit限制
User.find().limit(1).exec(function(err,data){
console.log(data);
})
由于limit必须是基于已经查询好的数据行中限制行数,所以必须在find之后,而limit本身不能传入回调函数,故而可以在最后使用exec执行,exec代表最终执行之前所有的链式方法。否则也没有别的办法取得链式之后想要的数据了。
注:对于那些(比如上述limit)不能提供回调函数,那么直到调用exec才会执行
select选择字段
User.find({email:"devil"}).select("email").exec(function(err,data){
console.log(data);
})
以上代码代表只看email字段,并且select也必须在find之后执行。
sort排序
首先搞清楚SQL中,asc升序,desc降序
//desc
User.find().sort("-email").exec(function(err,data){
console.log(data);
})
//asc
User.find().sort("email").exec(function(err,data){
console.log(data);
})
上面是按照email排序,前面加了负号就是降序,不加负号就是升序。
skip跳过就不说了。
总结:find是找到数据,select,limit,sort,skip等都是筛选操作,都必须在find之后执行,否则要报找不到func错误!
另外select,limit,sort,skip并不能传入回调函数,所以最终获取数据都必须依靠最后一次exec传入回调函数获取!
将js进行到底:node学习9的更多相关文章
- 【特别推荐】Node.js 入门教程和学习资源汇总
这篇文章与大家分享一批很有用的 Node.js 入门教程和学习资源.Node 是一个服务器端的 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...
- Node.js 入门教程和学习资源汇总
这篇文章与大家分享一批很有用的 Node.js 入门教程和学习资源.Node 是一个服务器端的 JavaScript 解释器,它将改变服务器应该如何工作的概念.它的目标是帮助程序员构建高度可伸缩的应用 ...
- Node.js环境搭建和学习(windwos环境)
Node.js环境搭建和学习 一.环境搭建 1.下载安装文件 下载地址http://nodejs-org.qiniudn.com/下载Node.js环境安装包,根据操作系统下载对应的安装包 下载地址 ...
- node 学习笔记 - Modules 模块加载系统 (1)
本文同步自我的个人博客:http://www.52cik.com/2015/12/11/learn-node-modules-path.html 用了这么久的 require,但却没有系统的学习过 n ...
- [学姿势]实验室搬砖+node学习
这周开始进行收尾工作,我当然没有进行核心技术的开发,主要负责的是对web端进行展示上的修修补补,主要包括添加VLC播放器.rtsp视频流以及一些js细节. 1.VLC 全称为Video Lan Cli ...
- 2015第40周二Node学习
node历史 今天看cnode开源项目用了io.js,在查这个项目时发现这篇文章node历史,node.js和io.js关系谈到Node.js的由来,不可避免要聊到它的创始人Ryan Dahl.在20 ...
- 2015第40周一Node学习
node学习尝试 早上看了张丹大牛博客文章nodeJS学习路线图和node从零入门系列,感觉获益匪浅,尝试了里面几项内容,对node有了更深入的认识. npm npm是一个node包管理和分发工具,已 ...
- Node学习——开篇
前言:自从下决心转学前端以来,我的专业课java基本荒废了,所以对于后台开发的逻辑也已基本忘干净了.但是作为一名准前端程序猿,我认为还是有必要了解后端开发的,虽不必深入学习,但是能够了解项目从前端到后 ...
- node 学习资料
Node 学习资料: 资料名称 网址 Node.js 中文API文档 http://nodejs.cn/api/ Node 菜鸟教程 http://www.runoob.com/nodejs/node ...
- Node学习HTTP模块(HTTP 服务器与客户端)
Node学习HTTP模块(HTTP 服务器与客户端) Node.js 标准库提供了 http 模块,其中封装了一个高效的 HTTP 服务器和一个简易的HTTP 客户端.http.Server 是一个基 ...
随机推荐
- sqlserver修改某列为自增
sqlserver如果建表的时候不设自增,之后是没法直接修改的,需要先删再重设: alter table 表名 drop column ID alter table 表名 add ID int ide ...
- Graph & Trees3 - 二分图
\[二分图略解\] \[By\;TYQ\] 二分图定义: \(f(i,L) = [a \in L\;\text{&}\;\forall b \in a.to \;\text{,}\; b \n ...
- [转载]markown语法
目录 Cmd Markdown 公式指导手册 一.公式使用参考 1.如何插入公式 2.如何输入上下标 3.如何输入括号和分隔符 4.如何输入分数 5.如何输入开方 6.如何输入省略号 7.如何输入矢量 ...
- Linux mint OS
Linux mint OS Ctrl+Alt left or right : # Change workspace Goldendict + Goldendict-wordnet # Dict for ...
- elasticsearch min_hash 应用分析
需求作相似文本查询 爬虫作页面去重,会用到simhash,第一个想到的是用simhash算法 但在现有数据集(elasticsearch集群)上用simhash,成本高,simhash值还好计算,不论 ...
- 关于前端jquery的总结
简介 jQuery是一个JavaScript库,特性丰富,包含若干对象和很多函数,可以代替传统DOM编程的操作方式和操作风格,通过对DOM API.DOM事件的封装,提供了一套全新的API,这套全新 ...
- Opencv笔记(四)——绘图函数
常用的绘图函数有: cv2.line() cv2.circle() cv2.rectangle() cv2.ellipse() cv2.putText( ...
- 吴裕雄--天生自然C语言开发:运算符
#include <stdio.h> int main() { ; ; int c ; c = a + b; printf("Line 1 - c 的值是 %d\n", ...
- 004.前端开发知识,前端基础CSS(2020-01-09)
一.CSS字体样式属性 1.font-size:字号大小 2.font-family:字体 font-family属性用于设置字体.网页中常用的字体有宋体.微软雅黑.黑体等. * { /*font-f ...
- Cisco路由器配置基本命令
特权模式:enable Router1 # show running-config Router1 # show ip route Router # show ip interface brief S ...