Nodejs之MongoDB,Mongoose初体验

       最近计划学习开发nodejs 搭建个人服务,在数据库选取上,选择了mongodb,至于该数据库有啥优劣,自行查询(可以参考这个 传送门)。本文通过mongodb基本工具--Mongodb campass--认识mongodb里面的一些数据概念,在到命令行基本操作使用Mongodb,再到mongoose工具对数据库的增删改查讲解。相对于入门来说,由浅入深,知识点还是比较全面的。有需要的童鞋可以参考一下。因为是第一次接触,自己查阅文档正在摸索中。可以当个入门参考。如有不足,还请各位看官多多指点。好了,话不多说,直接开始正文吧。

MongoDB安装与简单了解

       首先呢 是安装MongoDB数据库。window上安装可以点击这里去下载安装。下载msi文件安装后,会在电脑上安装mongoDB这个非关系型数据库,和一个可视化的图形工具 MongoDB Campass (4.0版本)。刚才也提到了,MongoDB是个非关系型数据库,那么他和我们常用的关系型数据库有啥差异呢?

       简单来说有如下对应关系

      

     详细的看如下图所示


        看上图中 一个数据行是以json 形式记录的,可以知道MongoDB 使用JSON(JavaScript ObjectNotation)文档存储记录。但是呢文档document的存放形式是类似于json 的Bjson格式存放的,也就是MongoDB中document以BSON形式存放。BSON目前主要用于MongoDB中,是MongoDB的数据存储格式。BSON基于JSON格式,选择JSON进行改造的原因主要是JSON的通用性及JSON的schemaless的特性。

       了解了基本数据格式我们开始操作数据库吧。首先我们先通过MongoDB Campass 这个工具简单操作一下数据库,了解一下collection集合  和document 是啥样的。

Mongodb campass 工具的初识

     1.创建 database

        点击 create database 打开创建窗口,填写database name 数据库名和collection name  集合名称,点击 create database 创建。注意 collection 必须制定一个,不然创建不了。


       2.创建collection

         找到要创建位置所在的数据库。点击右侧的CREATE COLLECTION,输入集合名字就能创建collection。

       3.插入 document

          点击进入 collection 在collection 上面有个 insert document 按钮,点击输入字段,字段类型 然后点击insert

       4. 插入 field

            在插入document的时候 可以添加字段:属性, 属性名, 属性类型

       创建完成后list形式如下图所示


       collection 集合 类似于关系型数据库的table ,点击上方的 list ,table 切换视图进行数据查看。list 可以看到我们需要的 json 数据结构 ,table 能清楚查看类似表一样的结构




好了,通过自带的工具,我们了解到了前面说的collection集合和document是什么样式的,我们可以在命令行中进行数据库的相关操作了。

Mongo基本命令行

1.查看已有的数据库及其数据集合

    (1)cmd输入 mongo 进入mongo环境, 显示出你的mongodb基本信息,

       (2)   接着输入 show dbs 查看本地的所有数据库列表。在列表中我们可以看到我们之前通过工具创建的数据库。

     (3)use  创建/切换数据库。use parkappdb

                是数据库名称。如果use后面的数据库存在,则切换到该数据库,如果不存在则创建。当我们切换到指定数据库后,不放心我们使用的数据库是否是我们要操作的数据库咋办?不用担心。我们可以输入 db   指令 查看当前所用数据库名称

     (4)show collections  显示当前数据库中的集合(类似关系数据库中的表)

               

2.查、增、改、删 操作

    (1)查询

        查询集合中存在的document数据记录。可使用 指令  db.collectionName.find() 

        db.users.find():对于当前数据库中的users集合进行数据查找(由于没有条件,会列出所有数据)。find方法里面可以传递参数(查询条件)。为了方便我们查看,我们可以使用db.users.find().pretty() 将查询结果格式化输出。


     (2)新增集合,插入数据

       创建集合db.createCollection(name, options) ,name是集合名称,options是可选参数, 指定有关内存大小及索引的选项。集合不存在也会自动创建。创建后我们可以在工具中查看集合的创建情况。


       插入数据db.testdb.insert({"test": "测试用例"})  在操作前可以对比工具中显示的数据情况,对比操作后的差异,会看到本没这个数据集合,但是这个插入语句执行后 自动添加了一个collection 并填充数据

(3)更新修改数据

      a)update 命令更新 

     基本语法如下

    db.colletionName.update(
         
        ,
        {
          upsert:,
          multi: ,
          writeConcern: 
        }
     )复制代码

    参数说明:
  • query : update的查询条件,类似sql update查询内where后面的。
  • update : update的对象和一些更新的操作符(如$,$inc...)等,也可以理解为sql update查询内set后面的
  • upsert : 可选,这个参数的意思是,如果不存在update的记录,是否插入objNew,true为插入,默认是false,不插入。
  • multi : 可选,mongodb 默认是false,只更新找到的第一条记录,如果这个参数为true,就把按条件查出来多条记录全部更新。
  • writeConcern :可选,抛出异常的级别。
上述代码中 $set 是更新操作符。$set修改器用来指定一个键值对,如果存在键就进行修改,不存在则进行添加。

       其他的修改操作符有

       $inc  修改器只是使用与数字类型,他可以为指定的键对应的数字类型的数值进行加减操作.

       $unset  修改器用法很简单,就是删除指定的键值对。

       $push 修改器:

                1.如果指定的键是数组增追加新的数值 

                 2.如果指定的键不是数组则中断当前操作。

                 会有提示 Cannot apply  $push/$pushAll modifier to non-array 

                 3.如果不存在指定的键则创建数组类型的键值对

                 4.此方法可添加重复数据

      $pushAll 修改器用法和$push相似,它可以批量添加数组数据 ,可以添加整个数组

      $addToSet 修改器是如果目标数组存在此项则不操作,不存在此项则加进去,即不添加重复                         数据。

      $pop 修改器从指定数组删除一个值1删除最后一个数值,-1删除第一个数值。

      $pull 修改器是删除一个被指定的数值。

      $pullAll 修改器是一次性删除多个指定的数值。

      $rename  对字段进行重命名

      以上操作符 请自己实际操作一下,不在赘述了。

      MongoDB的CURD参考1 

      b)save命令     db.collection.save(obj)

        obj代表需要更新的对象,如果集合内部已经存在一个和obj相同的"_id"的记录,  Mongodb会把obj对象替换集合内已存在的记录,如果不存在,则会插入obj对象。

(4)删除

   db.[collectionName].remove({key:value})   根据条件删除数据 

   db.[collectionName].remove({})   删除集合中所有数据 而集合的本身和索引不会被删除

   db.[collectionName].remove({})  删除集合中所有数据 ,集合的本身和索引不会被删除

   db.collection.drop()  删除整个集合。集合、索引都不存在了

经过以上操作。我们基本熟悉了 mongodb 命令行的相关操作。接下来我们看看如何给mongodb 设置权限,设置用户名密码


3.MongoDB 设置权限 (设置用户名密码)

在设置某个数据库用户名密码之前要先设置数据库用户管理员

 (1)创建用户管理员,设置最高权限

           a) use admin  切换数据库,进入admin 数据库下进行创建

use  admin
db.createUser({
    user:'root',
    pwd:'root',
    roles:[{role:"root",db:"admin"}]
})复制代码

   // mongodb中的用户是基于身份role的,该管理员账户的role是 root 代表超级管理员权限

创建成功会有相应提示


          MongoDB数据库角色有如下所示

    • 数据库用户角色:read、readWrite; 
    • 数据库管理角色:dbAdmin、dbOwner、userAdmin;
    • 集群管理角色:clusterAdmin、clusterManager、clusterMonitor、hostManager;
    • 备份恢复角色:backup、restore;
    • 所有数据库角色:readAnyDatabase、readWriteAnyDatabase、userAdminAnyDatabase、dbAdminAnyDatabase 
    • 超级用户角色:root // 这里还有几个角色间接或直接提供了系统超级用户的访问 (dbOwner 、userAdmin、userAdminAnyDatabase)
    • 内部角色:__system 

          角色说明: 

    • Read:允许用户读取指定数据库 
    • readWrite:允许用户读写指定数据库 
    • dbAdmin:允许用户在指定数据库中执行管理函数,如索引创建、删除,查看统计或访问 system.profile 
    • userAdmin:允许用户向system.users集合写入,可以找指定数据库里创建、删除和管理用户 
    • clusterAdmin:只在admin数据库中可用,赋予用户所有分片和复制集相关函数的管理权限。
    • readAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读权限
    • readWriteAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的读写权限     
    • userAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的userAdmin权限 
    •  dbAdminAnyDatabase:只在admin数据库中可用,赋予用户所有数据库的dbAdmin权限。 
    •  root:只在admin数据库中可用。超级账号,超级权限

           b)修改配置文件,开启安全认证

                修改配置文档mongod.cfg(位置:安装目录\bin 下)找到 #security      
               修改为
                      security:
                      authorization: enabled #注意缩进,enabled 前面有个空格。

                     

               重启MongoDB Server服务,启用认证。在本机“服务“”里找到 mongodb 重启
              重新进入mongo 环境执行语句,会提示认证

        

        c)进行认证

          'db.auth(用户名,用户密码)'   认证只能在admin 库下进进行认证,在其他库下认证会不通过,在admin 认证后可以去其他库进行操作如果返回 '1'表示验证成功,如果是 '0' 表 示验证失败


(2)为某个数据库设置用户权限

          首先确定以用户管理员的身份登录 admin 数据库。然后用 use 命令切换到目标数据 库,同样用 db.createUser() 命令来创建用户,其中角色名为 “readWrite” > 

>use test 
switched to db test
> db.createUser({
      user:"testuser",
      pwd:"testpass",
      roles:["readWrite"]}) 
Successfully added user: { "user" : "testuser", "roles" : [ "readWrite" ] }
> db.auth("testuser","testpass")
1复制代码

Mongoose使用

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

Mongoose的api

在使用这个框架工具之前呢先简单了解一下几个概念,因为在Mongoose中会用到。

Schema:

       一种以文件形式存储的数据库模型骨架,无法直接通往数据库端,也就是说它不具备对数据库的操作能力.可以说是数据属性模型(传统 意义的表结构),又或着是“集合”的模型骨架。Schema是以key-value形式Json格式的数据

model:

   数据模型,模型具有对数据库操作的能力。我们需要将 schema转换为model 进行数据操作


1.安装mongoose到项目里

 npm install mongoose 

2. 引入mongoose

      consnt mongoose = require('mongoose')

3.连接数据库

     先确定数据库地址。格式为 mongodb://userName:pwd@ip:port/dbname

      例如 mongodb://root:root@localhost:27017/test

       connect 方式连接

//--------创建连接 ------------ 
mongoose.connect(DBURL,function(err){
    if(err){
        console.warn('数据库连接失败:'+err);
    }else {
        console.log('数据库成功连接到');
    }
 }); 
//---------创建一个Schema ----------
 var userchema = mongoose.Schema({
     testIndex:Number,
     testName:String,
     testVal:'string'
    })
//---------创建model---------------
var userModel = mongoose.model('user',userchema,‘集合名字’ ); 

//--参数一为Model的名字,参数二为生成Model所需要的schema,Model就像是schema所编译而成的一样。 //--默认情况下model会自动根据 user 这个名字 加上s 即 users 为集合collection 的名字。 
//我们可以自定义集合的名字,有如下2种写法
//-----------方式1------------------------------------- 
//var userchema = mongoose.Schema({},{ collection:'集合名字' } ) 
//userModel = mongoose.model('user',userchema );
//-----------方式2-------------------------------------
// var userchema = mongoose.Schema({})
 //var userModel = mongoose.model('user',userchema,‘集合名字’ ); 
复制代码

         schemas中的数据类型有以下几种: 

                String :字符串类型 

                Number :数字类型 

                Date : 日期类型 

                Boolean :boolean类型 

                Buffer :NodeJS buffer类型 

                ObjectId :主键,一种特殊而且非常重要的类型 

                Mixed : 混合类型 , Schema = new mongoose.Schema({any:{mixed}})

                Array: 集合类型 

       connect + connection 方式连接

       因为connect()方法并不能监听数据库连接情况,而connection是mongoose模块的默认引用,返回一个Connetion对象。所 以 connect 和connection 搭配使用,可以对数据库连接情况监听。

mongoose .connect(DBURL) 
var mgdbconect =mongoose.connection;
mgdbconect.on('状态',function(){})
//----可选状态有 connected disconnected error 
//---创建schmea 和创建 model 跟上述一致复制代码

       createConnection()   方式连接

mongoose.createConnection([uri], [options], [options.config], 
[options.config.autoIndex, [options.useMongoClient]) 
//--此方法获取数据库连接,操作database层面,返回一个Connection对象。 
//Connection对象中包含model,collection,dropDatabase等操作数据库的方法,
//也包含connected,disconnected,error等事件触发方法。
//---具体操作请查阅相关资料复制代码

      上述几种方式简单区别如下

      1、createConnetion()方法的返回值是一个Connetion,可以使用createConnetion操作多个数据库。 

      2、connet()方法的返回值中包含了一个mongoose的引用,所以在项目中只能对一个数据库操作,而在操作多个数据库的情况下,可以 使用createConnetion()方法。

     3、connection是mongoose模块的默认连接。返回一个Connetion对象 

4.查询数据

    Mongoose 模型提供了 find, findOne, 和 findById 方法用于文档查询 

    Model.find(query, fields, options, callback) // fields 和 options 都是可选参数

    //query 查询条件,   fields 要查询字段 ,options 配置项 ,callback 回调函数

在第二个参数中,指定键名且值为1或者true则是查询结果中显示的键;若值为0或者false,则为不显示键。文档中的键若在参数中没有指定,查询结果中将不会显示(_id例外)。_id是默认显示的,除非进行手动设置为0或者false则不显示。 

//---   UserModel 是上面进行数据库连接的时候创建的model
UserModel.find({},function(err,docs){
        if(err){
            console.log('查询出错啦')
        }else{
            console.log('全部查询结果--',docs) 
        }
});
//----查询 testname 为测试 的数据,并返回  testIndex  testVal 这两个字段的结果
UserModel.find({testName:'测试'},{testIndex:1,testVal:1},{},function(err,docs){
        if(err){
            console.log('查询出错啦')
        }else{
            console.log('testName==测试-查询结果--',docs)
        }
});复制代码

    Model.findOne   

           与 Model.find 相同,但只返回单个文档

    Model.findOne({ userNname:"张三"},function(err, doc){// doc 是单个文档}); 

    Model.findById 

           与 findOne 相同,但它接收文档的 _id 作为参数,返回单个文档。_id 可以是字符串或       ObjectId 对象。 

    Model.findById(obj._id,function(err, doc){// doc 是单个文档});

    按照条件查询

    Model.countDocuments

      返回符合条件的文档数。

     Model.countDocuments(conditions, callback);

    Model.distinct

       查询符合条件的文档并返回根据键分组的结果。

    Model.distinct(field, conditions, callback);

    Model.where (path, [val]) 

       path实际上就是字段, 第二个参数val表示可以用来指定path = val的数据内容

//--多条件查询示例  查询testIndex大于3,且testname为测试的数据
Model.where('testIndex').gt(3).
    where({'testName':'测试'}).
    select('testVal').
    exec(function(err,res){
        console.log('testIndex大于3,且testname为测试 的结果--',err,res)
});复制代码

     Model.$where

       有时我们需要在 mongodb 中使用 javascript 表达式进行查询,这时可以用      find({$where : javascript}) 方式,$where 是一种快捷方式,并支持链式调用查询。

//--示例
UserModel.$where('this.testName === this.testVal').exec(function(err,res){
    console.log('name val相同的结果---',err,res)
});复制代码

      以上查询都带有返回函数。如果不提供回调函数,所有这些方法都返回 Query 对象,它们都可以被再次修改(比如增加选项、键等),直到调用 exec 方法。 

 var query =Model.find({});
 query.where('field',5); 
 query.limit(5); 
 query.skip(100); 
 query.exec(function(err, docs){
    // called when the `query.complete` or `query.error` are called// internally
 }); 
 //--以上callback 函数 返回的第一个参数是err 第二个参数是doc 查询结果存放于doc中 复制代码

     更多参考 www.cnblogs.com/chris-oil/p…

5.新增数据

       新增数据有2种方式  model.create() 和 model.save() 

        mode.create()可以一次性新增多条数据 

        mode.save() 需要实例化 model 才能新增 所以只能新增一条数据

  //------create新增  
    UserModel.create(
        {testIndex:12,testName:'create的数据',testVal:'create的数据'},
        {testIndex:13,testName:'create的数据',testVal:'create'},
        function(err,doc){
            console.log('create创建2条数据结果---',err,doc)
    });
//---save 新增--
    const testUserModel = new UserModel({
        testIndex:14,
        testName:'save的数据',
        testVal:'save'
    })
    testUserModel.save(function(err,doc){
       console.log('save创建1条数据结果---',err,doc)
    });
复制代码

6. 更新数据

       Model.update(conditions, doc, [options], [callback])
       conditions:查询条件;

       doc:需要修改的数据,不能修改主键(_id); 

       options:控制选项; 

       callback:回调函数,返回的是受影响的行数。

    options有以下选项
  safe (boolean): 默认为true。安全模式。
  upsert (boolean): 默认为false。如果不存在则创建新记录。
  multi (boolean): 默认为false。是否更新多个查询记录。
  runValidators: 如果值为true,执行Validation验证。
  setDefaultsOnInsert: 如果upsert选项为true,在新建时插入文档定义的默认值。
  strict (boolean): 以strict模式进行更新。

       overwrite(boolean) 默认为false。禁用update-only模式,允许覆盖记录

 // -----更新 修改  Model.update(conditions, doc, [options], [callback])
UserModel.update({ testName:'save的数据'},{testName:'手机',testVal:'oppo'},function(err,doc){
    console.log('更新一条数据--',err,doc)
}); 
UserModel.update({testName:'create的数据'},{testName:'快递',testVal:'顺丰'},{multi: true},
 function(err,doc){
    console.log('更新多条数据--',err,doc)
});复制代码

其他的更新方法 

 Model.updateMany(conditions, doc, [options], [callback])   //一次更新多条                 Model.updateOne(conditions, doc, [options], [callback])  //一次更新一条           Model.findByIdAndUpdate(id, [update], [options], [callback]) 

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

     根据id进行更新;此id就是数据库中自动生成的id ,

     id:指定_id的值;

     update:需要修改的数据;

     options控制选项;

     callback回调函数。 

    options有以下选项:

       new:bool - 默认为false。返回修改后的数据。

       upsert: bool - 默认为false。如果不存在则创建记录。

       runValidators: 如果值为true,执行Validation验证。

       setDefaultsOnInsert: 如果upsert选项为true,在新建时插入文档定义的默认值。            sort: 如果有多个查询条件,按顺序进行查询更新。

       select: 设置数据的返回。

       passRawResult: 如果为真,将原始结果作为回调函数第三个参数。

7.删除

    Model.remove(conditions, [callback]) //---删除 

UserModel.remove({testName:'待删除'},function(err,docs){ 
  console.log('删除了-',err,docs) 
})  //--删除“testName”值为“待删除”的记录。复制代码

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

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

    id:指定_id的值;

    conditions:查询条件;

    update:需要修改的数据;

    options控制选项;

    callback回调函数。 

    options有以下选项: 

       sort: 如果有多个查询条件,按顺序进行查询更新。

       select: 设置数据的返回。 

       maxTimeMS: 查询用时上限。

附上本文示例代码

var  mongoose = require('mongoose'),
    DB_URL ='mongodb://appadmin:admin@localhost:27017/parkappdb';

    /* 连接*/ 
    mongoose.connect(DB_URL,{ useNewUrlParser: true });

    var mgdbconect  =mongoose.connection;

    mgdbconect.on('connected',function(){
        console.log('已连接');
    })

    mgdbconect.on('error',function(error){
        console.log('连接出错:' +error);
    })

    mgdbconect.on('disconnected',function(){
        console.log('未连接');
    })
    //--定义数据结构模板
    const userSchema = new mongoose.Schema({
        testIndex:Number,
        testName:String,
        testVal:'string'
    })
    //---modle 实例化 schema
    const UserModel = mongoose.model('user',userSchema,'testDEMO')
    // Mongoose 模型提供了 find, findOne, 和 findById 方法用于文档查询。
    // Model.find(query, fields, options, callback)// fields 和 options 都是可选参数
    UserModel.countDocuments({},function(err,res){
        console.log('计数--',err,res)
        console.log("----------------------------")
    })
    //查询  ----------------------------------------------------
    UserModel.find({},function(err,docs){
        if(err){
            console.log('查询出错啦')
        }else{
            console.log('全部查询结果--',docs)   
            console.log("----------------------------")
        }
    });
    UserModel.find({testName:'测试'},{testIndex:1,testVal:1},{},function(err,docs){
        if(err){
            console.log('查询出错啦')
        }else{
            console.log('testName==测试-查询结果--',docs)   
            console.log("----------------------------")
        }
    });
    UserModel.where('testIndex').gt(3).where({'testName':'测试'}).select('testVal').exec(function(err,res){
        console.log('testIndex大于3,且testname为测试 的结果--',err,res)
        console.log("----------------------------")
    });
    UserModel.$where('this.testName === this.testVal').exec(function(err,res){
        console.log('name val相同的结果---',err,res)
        console.log("----------------------------")
    });
    //------新增  
    UserModel.create(
        {testIndex:12,testName:'create的数据',testVal:'create的数据'},
        {testIndex:13,testName:'create的数据',testVal:'create'},
        function(err,doc){
            console.log('create创建2条数据结果---',err,doc)
    });
    const testUserModel = new UserModel({
        testIndex:14,
        testName:'save的数据',
        testVal:'save'
    })
    testUserModel.save(function(err,doc){
        console.log('save创建1条数据结果---',err,doc)
    });
    // -----更新 修改  Model.update(conditions, doc, [options], [callback])
    UserModel.update({ testName:'save的数据'},{testName:'手机',testVal:'oppo'},function(err,doc){
        console.log('更新一条数据--',err,doc)
    }); 
    UserModel.update(
        { testName:'create的数据'},{testName:'快递',testVal:'顺丰'},{multi: true},function(err,doc){
        console.log('更新多条数据--',err,doc)
    });
    //---删除 
    UserModel.remove({testName:'待删除'},function(err,docs){
        console.log('删除了-',err,docs)
    })
复制代码


以上就是关于MongoDB 及其mongoose工具的入门讲解及示例。因为是刚学习,有许多理解不准确的地方,还望大家指出,多多学习。thxs


转载于:https://juejin.im/post/5cc7e414f265da0356323f5a

你可能感兴趣的:(Nodejs之MongoDB,Mongoose初体验)