• Mongoose使用——nodejs结合mongodb


     0. 前言:

    Mongoose是NodeJS的驱动,不能作为其他语言的驱动。Mongoose有两个特点:

    • 通过关系型数据库的思想来设计非关系型数据库
    • 基于mongodb驱动,简化操作

      Mongooose中,有三个比较重要的概念,分别是Schema、Model、Document。它们的关系是:Schema生成Model,Model创造Document,Model和Document都可对数据库操作造成影响,但Model比Document更具操作性。

      Schema用于定义数据库的结构。类似创建表时的数据定义(不仅仅可以定义文档的结构和属性,还可以定义文档的实例方法、静态模型方法、复合索引等),每个Schema会映射到mongodb中的一个collection,Schema不具备操作数据库的能力。

      Model是由Schema编译而成的构造器,具有抽象属性和行为,可以对数据库进行增删查改。Model的每一个实例(instance)就是一个文档document。

      Document是由Model创建的实体,它的操作也会影响数据库。

    1. 安装

    在此之前需要安装nodejs和mongodb,才能使用npm来安装mongoose

    npm install mongoose

    项目中可使用下面的命令安装mongoose并自动将其添加到依赖

    npm i mongoose --save

    2. 连接数据库

    2.1 首先使用 require() 引入mongoose

    var mongoose = require('mongoose');

    2.2 使用 connect() 来连接mongodb数据库

    mongoose.connect(url);

    connect()最简单的使用方式,就是只要传入url参数即可,如下所示。

    /*直接连接*/
    mongoose.connect("mongodb://127.0.0.1/mongoose_test" );
    /*传递用户名密码来连接*/
    mongoose.connect('mongodb://username:password@host:port/database?options...');

    注意:mongoose版本大于或等于4.11.0时,连接数据库会提示warning(不影响运行),避免的方法添加userMongoClient的设置,且属性值为true

    mongoose.connect('mongodb://数据库的ip地址:端口号/数据库名', { useMongoClient: true});

    connect()方法还接受一个选项对象options,该对象将传递给底层驱动程序。

    mongoose.connect(uri, options);

    可用选项如下所示,更多详见参考,options 所包含的所有选项优先于连接字符串中传递的选项

     db            -数据库设置
     server        -服务器设置
     replset       -副本集设置
     user          -用户名
     pass          -密码
     auth          -鉴权选项
     mongos        -连接多个数据库

    如果要连接多个数据库,只需要设置多个url以,隔开,同时设置mongos为true

    mongoose.connect('urlA,urlB,...', {
       mongos : true 
    })

    connect()函数还接受一个回调参数,来判断是否连接成功

    mongoose.connect(uri, options, function(error) {
    
    });
    var mongoose = require('mongoose');
    mongoose.connect("mongodb://localhost/mongoose_test", function(err) {
        if(err){
            console.log('连接失败');
        }else{
            console.log('连接成功');
        }
    });

    2.3 使用 disconnect() 断开数据库连接(一般不需要调用)

    MongoDB数据库,一般情况下,只需要连接一次,连接一次以后,除非项目停止服务器关闭,否则连接一般不会断开

    mongoose.disconnect();

    2.4 监听MongoDB数据库的连接状态

    在mongoose对象中,有一个属性叫做connection,该对象表示的就是数据库连接。通过监视该对象的状态,可以来监听数据库的连接与断开

    数据库连接成功的事件

    mongoose.connection.once("open",function(){});

    数据库断开的事件

    mongoose.connection.once("close",function(){});

    3. Schema

    Schema主要用于定义MongoDB中集合Collection里文档document的结构。  

    定义Schema需要指定字段名和类型,支持的类型包括以下9种

    String      字符串
    Number      数字    
    Date        日期
    Buffer      二进制
    Boolean     布尔值
    Mixed       混合类型
    ObjectId    对象ID    
    Array       数组
    Decimal128  Decimal类型

    通过mongoose.Schema来调用Schema,然后使用new方法来创建schema对象

    var mongoose = require("mongoose");
    mongoose.connect("mongodb://127.0.0.1/mongoose_test",{useMongoClient:true});
    mongoose.connection.once("open",function () {
        console.log("数据库连接成功~~~");
    });
    
    //将mongoose.Schema 赋值给一个变量
    var Schema = mongoose.Schema;
    
    //创建Schema(模式)对象
    var stuSchema = new Schema({
        name:String,
        age:Number,
        gender:{
            type:String,
            default:"female"
        },
        address:String
    });

    [注意]创建Schema对象时,声明字段类型有两种方法,一种是首字母大写的字段类型,另一种是引号包含的小写字段类型

    var mySchema = new Schema({title:String, author:String});
    //或者 
    var mySchema = new Schema({title:'string', author:'string'});

    如果需要在Schema定义后添加其他字段,可以使用add()方法

    var MySchema = new Schema;
    MySchema.add({ name: 'string', color: 'string', price: 'number' });

    4. Model & Document

    模型Model是根据Schema编译出的构造器,或者称为类,通过Model可以实例化出文档对象document。文档document的创建和检索都需要通过模型Model来处理

    mongoose.model();

    [注意]一定要将model()方法的第一个参数和其返回值设置为相同的值,否则会出现不可预知的结果

      Mongoose会将集合名称设置为模型名称的小写版。如果名称的最后一个字符是字母,则会变成复数;如果名称的最后一个字符是数字,则不变;如果模型名称为"MyModel",则集合名称为"mymodels";如果模型名称为"Model1",则集合名称为"model1"。

    实例化文档document

    var StuModel = mongoose.model("student" , stuSchema);
    //Document 和 集合中的文档一一对应 , Document是Model的实例  通过Model查询到结果都是Document
    //创建一个Document
    var stu = new StuModel({
        name:"孙悟空",
        age:18,
        gender:"male",
        address:"花果山"
    });

    文档保存

    通过new StuModel()创建的文档stu,必须通过save()方法,才能将创建的文档保存到数据库的集合中,集合名称为模型名称的小写复数版

    //回调函数是可选项,第一个参数为err,第二个参数为保存的文档对象
    save(function (err, doc) {})
    stu.save(function (err) {
      if (err) return handleError(err);
    })

    也可减少步骤,直接向数据库插入文档

    var StuModel = mongoose.model("student" , stuSchema);
    
    //向数据库中插入一个文档
    //StuModel.create(doc, function(err){});
    StuModel.create({
        name:"白骨精",
        age:16,
        address:"白骨洞"
    },function (err) {
        if(!err){
            console.log("插入成功~~~");
        }
    });

    结果

      

    5. Model对象的方法

        

    有了Model,我们就可以来对数据库进行增删改查的操作了。具体方法可参考官方文档

    5.1 增加方法

    Model.create(doc(s), [callback])
         - 用来创建一个或多个文档并添加到数据库中
         - 参数:
             doc(s) 可以是一个文档对象,也可以是一个文档对象的数组
             callback 当操作完成以后调用的回调函数
    StuModel.create([
        {
            name:"沙和尚",
            age:38,
            gender:"male",
            address:"流沙河"
        }
    
    ],function (err) {
        if(!err){
            console.log(arguments);
        }
    });

    控制台输出

    5.2 修改方法

     Model.update(conditions, doc, [options], [callback])
     Model.updateMany(conditions, doc, [options], [callback])
     Model.updateOne(conditions, doc, [options], [callback])
         - 用来修改一个或多个文档
         - 参数:
             conditions 查询条件
             doc 修改后的对象
             options 配置参数
             callback 回调函数
     Model.replaceOne(conditions, doc, [options], [callback])
    StuModel.updateOne({name:"唐僧"},{$set:{age:20}},function (err) {
        if(!err){
            console.log("修改成功");
        }
    });

     5.3 查询方法

    Model.find(conditions, [projection], [options], [callback])
          - 查询所有符合条件的文档 总会返回一个数组
    Model.findById(id, [projection], [options], [callback])
          - 根据文档的id属性查询文档
    Model.findOne([conditions], [projection], [options], [callback])
          - 查询符合条件的第一个文档 总会返回一个具体的文档对象(非数组)
    
             conditions 查询的条件
             projection 投影 需要获取到的字段
                 - 两种方式
                     {name:1,_id:0}
                     "name -_id"
             options  查询选项(skip limit)
                     {skip:3 , limit:1}
             callback 回调函数,查询结果会通过回调函数返回
                         回调函数必须传,如果不传回调函数,压根不会查询

    官方文档查询方法截图如下

    下面分别演示几种不同的查询方法

    //查询name为“唐僧”的
    StuModel.find({name:"唐僧"},function (err , docs) {
        if(!err){
            console.log(docs);
        }
    });

    结果

    //只查询name,且不查询_id  (_id字段默认输出)
    StuModel.find({},{name:1 , _id:0},function (err , docs) {
        if(!err){
            console.log(docs);
        }
    });

    结果

    //只查询文档的name,age值,查询时跳过3个,结果集限制只查询出一个
    StuModel.find({},"name age -_id", {skip:3 , limit:1} , function (err , docs) {
        if(!err){
            console.log(docs);
        }
    });

    结果

    StuModel.findOne({} , function (err , doc) {
        if(!err){
            console.log(doc);
        }
    });

    结果

    StuModel.findById("59c4c3cf4e5483191467d392" , function (err , doc) {
        if(!err){
            //console.log(doc);
            //通过find()查询的结果,返回的对象,就是Document,文档对象
            //Document对象是Model的实例
            console.log(doc instanceof StuModel);
        }
    });

    结果

    5.4 删除方法

     Model.remove(conditions, [callback])
     Model.deleteOne(conditions, [callback])
     Model.deleteMany(conditions, [callback])
    StuModel.remove({name:"白骨精"},function (err) {
        if(!err){
            console.log("删除成功~~");
        }
    });

    5.5 统计

     Model.count(conditions, [callback])
         - 统计文档的数量的
    StuModel.count({},function (err , count) {
        if(!err){
            console.log(count);
        }
    });

     6. Document对象的方法

    Document 和 集合中的文档一一对应,Document是Model的实例。通过Model查询到结果都是Document。

      

    6.1 保存

    save([options], [options.safe], [options.validateBeforeSave], [fn])
    //创建一个Document
    var stu = new StuModel({
        name:"奔波霸",
        age:48,
        gender:"male",
        address:"碧波潭"
    });
    //保存改document对象
    stu.save(function (err,product,numAffected) { //返回三个对象 err:失败信息; product:保存的对象; numAffected:该document对象被持久化了为1,否则为0
    if(!err){ 
        console.log("保存成功~~~");
    }

    6.2 更新

    update(update,[options],[callback])
    doc.update({$set:{age:28}},function (err) {
                if(!err){
                    console.log("修改成功~~~");
                }
    });

    或者对document对象进行修改,再执行save()方法

    doc.age = 28;
    doc.save();

    6.3 删除

    remove([callback])
    doc.remove(function (err) {
                if(!err){
                    console.log("删除成功~~~");
                }
      });

    6.4 其他

    get(name)
         - 获取文档中的指定属性值
    set(name , value)
         - 设置文档的指定的属性值
    id
         - 获取文档的_id属性值
    toJSON() ******
         - 转换为一个JSON对象
    toObject()
         - 将Document对象转换为一个普通的JS对象【转换为普通的js对象以后,注意所有的Document对象的方法或属性都不能使用了】
    console.log(doc.get("age"));
    console.log(doc.age);
    
    doc.set("name","猪九戒");
    doc.name = "hahaha";
    
    console.log(doc._id);
    var j = doc.toJSON();
    console.log(j);
    
    var o = doc.toObject();
    console.log(o);
    
    doc = doc.toObject();
    delete doc.address;
    
    console.log(doc._id);

    参考:

    官方文档

    Mongoose基础入门

    尚硅谷培训课程

  • 相关阅读:
    相机篇
    ValueAnimator动画跳过中间过程的问题
    android 双向文字问题
    android让xml布局的底部跟随软键盘
    给fragment设置进入和退出动画
    android布局控件的LayoutParams
    注意点
    关于与条件判断中的顺序
    栈的反转
    从尾到头打印链表
  • 原文地址:https://www.cnblogs.com/zjfjava/p/8733613.html
Copyright © 2020-2023  润新知