Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门

https://www.cnblogs.com/zhongweiv/p/mongoose.html

http://www.cnblogs.com/zhongweiv/p/node_mongodb.html


Nodejs学习笔记(十四)— Mongoose介绍和入门

目录

简介

  Mongoose是在node.js异步环境下对mongodb进行便捷操作的对象模型工具

  那么要使用它,首先你得装上node.js和mongodb,关于mongodb的安装和操作介绍可以参考:http://www.cnblogs.com/zhongweiv/p/node_mongodb.html

 

  Github地址:https://github.com/Automattic/mongoose

  API Docs:http://mongoosejs.com/docs/guide.html

 

  前面有介绍过用node-mongodb-native来操作mongodb,实际开发中估计更多会选用类似mongoose的模块来操作来提升开发效率

 

  下面我们一步步来了解mongoose的基本操作^_^!

 

mongoose安装

npm install mongoose

  安装成功后如下图:

Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第1张图片

  安装成功后,就可以通过 require('mongoose') 来使用!

 

连接字符串

  创建一个db.js

复制代码
var mongoose = require('mongoose'),
    DB_URL = 'mongodb://localhost:27017/mongoosesample';

/**
 * 连接
 */
mongoose.connect(DB_URL);

/**
  * 连接成功
  */
mongoose.connection.on('connected', function () {    
    console.log('Mongoose connection open to ' + DB_URL);  
});    

/**
 * 连接异常
 */
mongoose.connection.on('error',function (err) {    
    console.log('Mongoose connection error: ' + err);  
});    
 
/**
 * 连接断开
 */
mongoose.connection.on('disconnected', function () {    
    console.log('Mongoose connection disconnected');  
});    
复制代码

  调用node db.js执行就会看到输出如下图

  从代码中可以看出,监听了几个事件,并且执行触发了connected事件,这表示连接成功

  connection中不止有如上几个事件,关键看你想要监听哪个事件。

 

  其它事件可以自行查看:http://mongoosejs.com/docs/api.html#connection_Connection

  

  这是最简单的连接字符串,当然还有其它形式,比如:连接密码、数据库连接设置、集群方式连式等等,这里解释了,用着了时候自行查询API文档

  http://mongoosejs.com/docs/api.html#index-js

  

Schema

  schema是mongoose里会用到的一种数据模式,可以理解为表结构的定义;每个schema会映射到mongodb中的一个collection,它不具备操作数据库的能力

  我们先改造一下db.js,导出mongoose对象  

复制代码
var mongoose = require('mongoose'),
    DB_URL = 'mongodb://localhost:27017/mongoosesample';

/**
 * 连接
 */
mongoose.connect(DB_URL);

/**
  * 连接成功
  */
mongoose.connection.on('connected', function () {    
    console.log('Mongoose connection open to ' + DB_URL);  
});    

/**
 * 连接异常
 */
mongoose.connection.on('error',function (err) {    
    console.log('Mongoose connection error: ' + err);  
});    
 
/**
 * 连接断开
 */
mongoose.connection.on('disconnected', function () {    
    console.log('Mongoose connection disconnected');  
});    

module.exports = mongoose;
复制代码

  下面我们定义一个user的Schema,命名为user.js

复制代码
/**
 * 用户信息
 */
var mongoose = require('./db.js'),
    Schema = mongoose.Schema;

var UserSchema = new Schema({          
    username : { type: String },                    //用户账号
    userpwd: {type: String},                        //密码
    userage: {type: Number},                        //年龄
    logindate : { type: Date}                       //最近登录时间
});
复制代码

  定义一个Schema就这么简单,指定字段名和类型

  Schema Types内置类型如下:

  String

  Number

  Boolean | Bool

  Array

  Buffer

  Date

  ObjectId | Oid

  Mixed

 

  Schema中还可以做一些常用事,后面再讲!

 

Model

  定义好了Schema,接下就是生成Model。

  model是由schema生成的模型,可以对数据库的操作

  我们对上面的定义的user的schema生成一个User的model并导出,修改后代码如下

复制代码
/**
 * 用户信息
 */
var mongoose = require('./db.js'),
    Schema = mongoose.Schema;

var UserSchema = new Schema({          
    username : { type: String },                    //用户账号
    userpwd: {type: String},                        //密码
    userage: {type: Number},                        //年龄
    logindate : { type: Date}                       //最近登录时间
});

module.exports = mongoose.model('User',UserSchema);
复制代码

 

常用数据库操作

  接下来创建一个test.js文件做一些常用操作演示。

  插入

  Model#save([fn])

复制代码
var User = require("./user.js");

/**
 * 插入
 */
function insert() {
 
    var user = new User({
        username : 'Tracy McGrady',                 //用户账号
        userpwd: 'abcd',                            //密码
        userage: 37,                                //年龄
        logindate : new Date()                      //最近登录时间
    });

    user.save(function (err, res) {

        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }

    });
}

insert();
复制代码

  结果在robmongo工具中查看

  从图中可以看到插入成功! 

 

  更新 

  Model.update(conditions, update, [options], [callback])

复制代码
var User = require("./user.js");

function update(){
    var wherestr = {'username' : 'Tracy McGrady'};
    var updatestr = {'userpwd': 'zzzz'};
    
    User.update(wherestr, updatestr, function(err, res){
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}

update();
复制代码

  根据用户名更新密码,执行后结果如图

  图中可以看出,密码更新成功!update方法基本可以满足所有更新!

  

  常用方法还有findByIdAndUpdate,这种比较有指定性,就是根据_id

  Model.findByIdAndUpdate(id, [update], [options], [callback])

复制代码
var User = require("./user.js");

function findByIdAndUpdate(){
    var id = '56f2558b2dd74855a345edb2';
    var updatestr = {'userpwd': 'abcd'};
    
    User.findByIdAndUpdate(id, updatestr, function(err, res){
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}

findByIdAndUpdate();
复制代码

  

  其它更新方法

  Model.findOneAndUpdate([conditions], [update], [options], [callback])      //找到一条记录并更新

  

  删除

  Model.remove(conditions, [callback])

复制代码
var User = require("./user.js");

function del(){
    var wherestr = {'username' : 'Tracy McGrady'};
    
    User.remove(wherestr, function(err, res){
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}

del();
复制代码

  结果就不贴了,res中会返回是否成功以及影响的行数:{"ok":1,"n":1}

 

  其它常用方法还有: 

  Model.findByIdAndRemove(id, [options], [callback])      

  Model.findOneAndRemove(conditions, [options], [callback])

 

  条件查询

  已先插入一些测试数据 。。

  Model.find(conditions, [fields], [options], [callback])

复制代码
var User = require("./user.js");

function getByConditions(){
    var wherestr = {'username' : 'Tracy McGrady'};
    
    User.find(wherestr, function(err, res){
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}

getByConditions();
复制代码

  结果我就不展示了

  第2个参数可以设置要查询输出的字段,比如改成

复制代码
var User = require("./user.js");

function getByConditions(){
    var wherestr = {'username' : 'Tracy McGrady'};
    var opt = {"username": 1 ,"_id": 0};
    
    User.find(wherestr, opt, function(err, res){
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}

getByConditions();
复制代码

  输出只会有username字段,设置方法如上,1表示查询输出该字段,0表示不输出

 

  比如我要查询年龄范围条件应该怎么写呢?

  User.find({userage: {$gte: 21, $lte: 65}}, callback);    //这表示查询年龄大于等21而且小于等于65岁

 

  其实类似的还有: 

  $or    或关系

  $nor    或关系取反

  $gt    大于

  $gte    大于等于

  $lt     小于

  $lte     小于等于

  $ne            不等于

  $in             在多个值范围内

  $nin           不在多个值范围内

  $all            匹配数组中多个值

  $regex  正则,用于模糊查询

  $size   匹配数组大小

  $maxDistance  范围查询,距离(基于LBS)

  $mod     取模运算

  $near   邻域查询,查询附近的位置(基于LBS)

  $exists    字段是否存在

  $elemMatch  匹配内数组内的元素

  $within  范围查询(基于LBS)

  $box    范围查询,矩形范围(基于LBS)

  $center       范围醒询,圆形范围(基于LBS)

  $centerSphere  范围查询,球形范围(基于LBS)

  $slice    查询字段集合中的元素(比如从第几个之后,第N到第M个元素)

  

  可能还有一些,没什么印象,大家自行看看api ^_^!  

 

  数量查询

  Model.count(conditions, [callback])

复制代码
var User = require("./user.js");

function getCountByConditions(){
    var wherestr = {};
    
    User.count(wherestr, function(err, res){
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}
getCountByConditions();
复制代码

  res会输出数量,也可以传入条件做条件查询!

  根据_id查询

  Model.findById(id, [fields], [options], [callback])

复制代码
var User = require("./user.js");

function getById(){
    var id = '56f261fb448779caa359cb73';
    
    User.findById(id, function(err, res){
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}

getById();
复制代码

  这个还是比较常用,要据ID得到数据!  

  模糊查询

复制代码
var User = require("./user.js");

function getByRegex(){
    var whereStr = {'username':{$regex:/m/i}};
    
    User.find(whereStr, function(err, res){
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}

getByRegex();
复制代码

  上面示例中查询出所有用户名中有'm'的名字,且不区分大小写,模糊查询比较常用,正则形式匹配,正则方式就是javascript正则,用到的比较多!

  分页查询

复制代码
var User = require("./user.js");

function getByPager(){
    
    var pageSize = 5;                   //一页多少条
    var currentPage = 1;                //当前第几页
    var sort = {'logindate':-1};        //排序(按登录时间倒序)
    var condition = {};                 //条件
    var skipnum = (currentPage - 1) * pageSize;   //跳过数
    
    User.find(condition).skip(skipnum).limit(pageSize).sort(sort).exec(function (err, res) {
        if (err) {
            console.log("Error:" + err);
        }
        else {
            console.log("Res:" + res);
        }
    })
}

getByPager();
复制代码

  分页是用得比较多的查询,分页原理用过其它数据库的都知道,分页用到的函数和mysql的比较类似

  上面我用到sort(),这个是排序规则,就不单讲了!

其它操作

  其它还有比较多常用的

  索引和默认值

  再看看我对user.js这个schema的修改

复制代码
/**
 * 用户信息
 */
var mongoose = require('./db.js'),
    Schema = mongoose.Schema;

var UserSchema = new Schema({          
    username : { type: String , index: true},                    //用户账号
    userpwd: {type: String},                        //密码
    userage: {type: Number},                        //年龄
    logindate : { type: Date, default:Date.now}                       //最近登录时间
});

module.exports = mongoose.model('User',UserSchema);
复制代码

  index :建索引

  default:默认值

  

  LBS地址位置

lbs : { type: Array, index: '2d', sparse: true }   //地理位置

  上面有介绍过很多基于LBS的条件查询,Schema中定义时如上

  LBS查询对于一些基于LBS应用会用得比较多。

 

  其它常用方法

  Model.distinct(field, [conditions], [callback])                  //去重

  Model.findOne(conditions, [fields], [options], [callback])             //查找一条记录

  Model.findOneAndRemove(conditions, [options], [callback])           //查找一条记录并删除

  Model.findOneAndUpdate([conditions], [update], [options], [callback])      //查找一条记录并更新

 

写在之后...

  mongoose操作基本入门大致就是这些,自已试一下,入门完全没问题,并且比node-mongodb-native还是要简单明了一些,

  在node.js中操作数据库,如果逻辑相对复杂时,大量的回调嵌套还是比较郁闷的,下一篇于mongoose操作多逻辑组合回调嵌套的问题给出一种方案^_^!




===================================================================


Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门

目录

  • 简介
  • MongoDB安装(windows)
  • MongoDB基本语法和操作入门(mongo.exe客户端操作)
    • 库操作
    • 插入
    • 查询
    • 修改
    • 删除
    • 存储过程
  • nodejs操作MongoDB
    • 插入
    • 查询
    • 修改
    • 删除
    • 调用存储过程
  • 写在之后...

简介

  MongoDB 

  开源,高性能的NoSQL数据库;支持索引、集群、复制和故障转移、各种语言的驱动程序;高伸缩性;

  NoSQL毕竟还处于发展阶段,也有说它的各种问题的:http://coolshell.cn/articles/5826.html

    官网地址:http://www.mongodb.org/

  API Docs:http://docs.mongodb.org/manual/

  node-mongodb-native

  mongodb的nodejs驱动;

  GitHub地址:https://github.com/mongodb/node-mongodb-native

MongoDB安装(windows)

  官方安装说明: http://docs.mongodb.org/manual/tutorial/install-mongodb-on-windows/

  按照官方说明在win7 64位环境下配置还是遇到了问题,我还是把我安装配置的过程写一下

  

  下载MongoDB并安装

  下载地址:http://www.mongodb.org/downloads

  创建数据库和日志存放目录

  在C盘根目录下新建“M_DB”和“M_LOG”两个文件夹,分别存放数据库文件和日志文件

  创建一个config文件

  打开目录“C:\Program Files\MongoDB 2.6 Standard\bin”,并在此目录下新建一个mongo.config文件,文件内容如下

##数据库目录
dbpath=C:\M_DB

##日志输出文件
logpath=C:\M_LOG\mongodb.log

  添加环境变量

  在环境变量PATH中加入“C:\Program Files\MongoDB 2.6 Standard\bin“

  以Windows服务器运行MongoDB

  以管理员方式打开CMD窗口,运行如下命令安装MongoDB服务,可以在 “控制面板\所有控制面板项\管理工具\服务”找到名为“MongoDB”的服务右键启动

mongod --config "C:\Program Files\MongoDB 2.6 Standard\bin\mongo.config" --install

  启动服务

  在CMD窗口中运行如下命令,也可以在可以在 “控制面板\所有控制面板项\管理工具\服务”

net start mongodb

  测试连接

  在CMD中运行如下命令,查看结果

mongo

  Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第2张图片

  安装成功!

 

  最后两步非必需;MongoDB默认端口是27017,可以修改!

 

  对于“C:\Program Files\MongoDB 2.6 Standard\bin”目录下的exe程序,做个简单的说明,可能更利于了解可以做些什么操作,基础学习关注mongod.exe和mongo.exe即可

  mongo.exe:客户端,支持js语法

  mongod.exe:服务端

  mongodump.exe:备份工具

  mongorestore.exe:恢复工具

  mongoexport.exe:导出工具

  mongoimport.exe:导入工具

  mongostat.exe:实时性能监控工具

  mongotop.exe:跟踪MongDB实例读写时间工具

 

  更多详细解释或操作可以查看:http://docs.mongodb.org/manual/reference/program/

MongoDB基本语法和操作入门(mongo.exe客户端操作)

  MongoDB已经安装好,下面先对MongoDB进行一个简单的入门,再用node-mongodb-native去操作MongoDB

  库操作

  新建数据库:第一步:use 新建数据库名;第二步:进行此库相关的操作;如果不进行第二步,该数据库不会被创建

  查看数据库:show dbs;

  新建表:db.createCollection('要新建的表名');

  查看当前数据库下表: show collections;

  删除当前数据库指定表:db.表名.drop();

  删除当前数据库:db.dropDatabase();

 

  示例操作如下图:

  Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第3张图片

  1.默认为存在“admin”和“local”两个数据库;admin数据库是存放管理员信息的数据库,认证会用到;local是存放replication相关的数据;这两处本篇都没有涉及到;

  2.find();是个查询操作,后面会讲到,上面用到主要是为了演示use不存在的库后,进行相关操作会创建出这个库;

  3.MongoDB没有像MySQL或MSSQL等数据库这么严格的规定,不是非得要先建库、建表、建各种字段,以后的操作中慢慢的会体会到^_^!

  

  插入

  方法一:db.表名.insert(数据);

  

  1.从上图操作可以看出,没有去创建“tb1”表,其实通过插入操作也会自动创建

  2._id,是mongodb自已生成的,每行数据都会存在,默认是ObjectId,可以在插入数据时插入这个键的值(支持mongodb支持的所有数据类型)  

  方法二:db.表名.save(数据);

     

  1.从上图操作可以看出,save也可达到insert一样的插入效果

  2._id可以自已插入

  3.一个表中不一定要字段都相同

 

  那它们有什么区别?

  Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第4张图片

  从图中操作就可以看出,虽然insert和save方法都可以插入数据,当默认的“_id”值已存在时,调用insert方法插入会报错;而save方法不会,会更新相同的_id所在行数据的信息

 

  查询  

  查询表中所有数据:db.表名.find();

  按条件查询(支持多条件):db.表名.find(条件); 

  查询第一条(支持条件):db.表名.findOne(条件);

  限制数量:db.表名.find().limit(数量);

  跳过指定数量:db.表名.find().skip(数量);

  

  从上图中可以看出具体用法,批量插入默认数据我用了一个javascript语法循环;

  

  比较查询

  大于:$gt

  小于:$lt

  大于等于:$gte

  小于等于:$lte

  非等于:$ne

  Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第5张图片

  上面看到了AND的关系,或者的关系应该怎么用?

  或者:$or

  

  

  in和not in查询(包含、不包含)
  $in
  $nin
   Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第6张图片 

 

  查询数量:db.表名.find().count();

  排序:db.表名.find().sort({"字段名":1}); 

     1:表示升序  -1:表示降序

  指定字段返回: db.表名.find({},{"字段名":0});  

     1:返回  0:不返回

  

  

  查询就讲到这里了,感觉查询示例一下讲不完,还有些高级查询,大家自行去了解一下吧^_^!

  

  修改

  前面save在_id字段已存在是就是修改操作,按指定条件修改语法如下

  db.表名.update({"条件字段名":"字段值"},{$set:{"要修改的字段名":"修改后的字段值"}});

  

 

  删除

  db.表名.remove(条件);

  Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第7张图片

 

  存储过程

   创建存储过程:

db.system.js.save({_id:"存储过程ID", 
value:function(参数){  
        -- 逻辑主体; 
        return 返回; 
}});                

  调用存储过程

db.eval("存储过程ID()");

  Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第8张图片

  所有存储过程都存放在db.system.js中

 

  MongoDB基本操作就讲这么多了,基本够用,深入学习大家自已去看看API^_^!

 

nodejs操作MongoDB

  先用npm安装mongodb

npm install mongodb

  安装成功后,继续在上面操作创建的库和表中操作

  

  插入

Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第9张图片

  示例源码

  查询

 Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第10张图片

复制代码
var MongoClient = require('mongodb').MongoClient;
var DB_CONN_STR = 'mongodb://localhost:27017/wilsondb1';  

var selectData = function(db, callback) {  
  //连接到表  
  var collection = db.collection('tb2');
  //查询数据
  var whereStr = {"name":'wilson001'};
  collection.find(whereStr).toArray(function(err, result) {
    if(err)
    {
      console.log('Error:'+ err);
      return;
    }     
    callback(result);
  });
}

MongoClient.connect(DB_CONN_STR, function(err, db) {
  console.log("连接成功!");
  selectData(db, function(result) {
    console.log(result);
    db.close();
  });
});
复制代码

  修改

  示例源码

  删除

Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第11张图片

  示例源码

  调用存储过程

Nodejs学习笔记(十四)— Mongoose介绍和入门 && Nodejs学习笔记(十)--- 与MongoDB的交互(mongodb/node-mongodb-native)、MongoDB入门_第12张图片

  示例源码

 

  到此CRUD操作就完成,通过回调函数的result参数进行判断都可以进行业务逻辑的进一步组合!

写在之后...

  本篇针对node-mongodb-native操作MongoDB没有做更深的讲解,原因是针对它的进行再次封装的东西很多,且更利于编程实现,比如:mongoose、mongoskin、mongolian等等,应用性不错;

  mongoose的可能用的比较多...

  本文中很多地方我都还是习惯的用表、行等术语去描述,其实对NoSQL来说并不对,只是有助于习惯了关系型数据库的开发人员来解;

  文章中“表”本应该描述为“collection(集合)”;“行”应该描述为“文档(document)”,一个database中可以有多个collection,一个collection中又可以有多个document

  文章中并没有涉及认证的部分,大家自行去补一下,非常简单,我文中也挺到了两个默认数据库中的“admin”数据库

  用CMD中使用mongo.exe操作时,插入中文遇一了问题,原因是MongoDB默认编辑是utf-8,而CMD是GBK,所以在CMD窗口中执行这个命令修改编辑即可:chcp 65001

  注意mongodb严格区分大小写,比如查询 db.tb2.find({"name":"wilson0"})和 db.tb2.find({"Name":"wilson0"}) 并不是用的同一字段做的条件;

 

  主要参考资料:

  http://docs.mongodb.org/manual/

  https://github.com/mongodb/node-mongodb-native

  MongoDB权威指南

作   者:   Porschev[钟慰] 
出   处:   http://www.cnblogs.com/zhongweiv/ 
微   博:     http://weibo.com/porschev 
欢迎任何形式的转载,但请务必注明原文详细链接


你可能感兴趣的:(mongodb,nodejs)