概念

Schema - 数据库存储格式的约定协议,可以理解为数据表的字段类型声明

Model -  由Schema转化的数据模型,具有抽象属性和行为的数据库操作,可以进行查询操作

Entity - 由Model创建的实体,可以对数据库表进行完整的CRUD操作

Mongoose使用

一、安装

    $ npm install mongoose

二、示例

    const mongoose = require('mongoose');
    const Schema = mongoose.Schema;

    // 连接mongodb
    mongoose.connect('mongodb://car:welcomeCar@localhost/myCar');       // mongodb://用户名:密码@数据库IP/库名

    // 连接成功
    mongoose.connection('connected', ()=>{
        console.log('connect success');
    })

    // 连接失败
    mongoose.connection('error', ()=>{
        console.log('connect error' + err);
    })

    // 连接断开
    mongoose.connection('disconnected', ()=>{
        console.log('connect disconnected');
    })

    // 创建Schema
    const UserSchema = new Schema({
        username: String,
        password: String,
        age: Number,
        LoginAt: Date
    })

    // 定义Model
    const UserModel = mongoose.model('User', UserSchema);

    // 插入数据
    let userData = new UserModel({
        username: 'siguang',
        password: 'ssssss',
        age: 20,
        loginAt: new Date()
    })

    // 保存
    userData.save((err, res)=>{
        if(err){
            return console.log(err)
        }
        console.log(res);
    })

    // 删除
    userData.remove({age: 30}, (err, doc) => {
        if(err){
            return console.log(err)
        }
        console.log(doc);
    })

    // 查询
    userData.find({username: 'siguang', (err, doc)=>{
        if(err){
            return console.log(err)
        }
        console.log(doc);
    })

    // 数量
    userData.count({age: 20}, (err, doc)=>{
        if(err){
            return console.log(err)
        }
        console.log(doc);
    })

连接

mongoose两种连接: connect连单个db并打开,createConnect连接多个db

一、mongoose.connect()方法连接

    写法1:
        connect('mongodb://[username]:[password]@host:port/database?options...');   // 用户名、密码、主机、端口、库名、参数
        let db = mongoose.connect('mongodb://[username]:[password]@127.0.0.1:27017/myDB');

    写法2:
        -- conect(uri, options) --
        var options = {
                db: { native_parser: true },
                server: { poolSize: 5 },
                replset: { rs_name: 'myReplicaSetName' },
                user: 'myUserName',
                pass: 'myPassword'
        }
        var uri = 'mongodb://localhost/dbName?poolSize=4';
        mongoose.connect(uri, options);
        -- mongoose.createConnection() --

二、多个连接

    let mongoose = require('mongoose');
    let db = mongoose.connect('mongodb://127.0.0.1:27017/myDB');        // mongodb://IP:端口号/数据库名

    // 侦听打开的回调
    db.connection.on('error', function(error){
        console.log('数据库连接失败'+error);
    })

    // 侦听连接成功
    db.connection.on('open', function(){
        console.log('连接成功')
    })

三、两者的区别

    var mongoose = require('mongoose');
    db = mongoose.createConnection('localhost', 'test');
    var schema = new mongoose.Schema({ name: String });
    var collectionName = 'kittens';
    var M = db.model('Kitten', schema, collectionName);

    var mongoose = require('mongoose');
    mongoose.connect('mongodb://localhost/test');
    db = mongoose.connection;
    db.once('open', function callback () {
            // yay!
    });    

    createConnection,可以open,但完全不会查询。第二种方法就可以

Schema

Schema: 一种文件形式存储数据库模型的骨架,无法直接连接数据端,不具备操作数据库的能力,叫数据属性模型或集合

一、定义表的文档结构

    let personSchema = new mongoose.Schema({        
        name: String,
        age: Number,
        email: { type: String, max: 20 }
    })

二、实例方法、静态方法

    let PersonSchema = new mongoose.Schema({        
        name: String,
        age: Number,
        email: { type: String, max: 20 }
    })

    var Person = mongoose.model('person', PersonSchema);
    var silence = new Person({ name: 'Silence' });

    PersonSchema.methods.speak = function(){ }

三、index 索引

    let Schema = mongoose.Schema;
    let carSchema = new Schema({
        name: String,
        title: { type: String, index: true },   // index 索引
        uid: { type: Number, unique: true },    // unique 独一无二的
        date: { type: Date, default: Date.now } // default 默认值
    })

    // 文档索引和字段索引
    let carSchema = new Schema({
        name: String,
        title: { type: [String], index: true },   // 字段索引
    })

    carSchema.index({ name: 1, type: -1});  // 

Schema Type

https://xiaoxiami.gitbook.io/mongoose/guide/schemas/typesmd

一、类型

    1、String:字符串

    2、Number:数值

    3、Date:日期

    4、Buffer: 二进制

    5、Boolean:布尔

    6、Mixed: 混合

    7、ObjectId: ObjectId

    8、Array:数组

二、其它参数

    default: 默认       // updated: { type: Date, default: Date.now }

    min/max: 最小或最大  // age: { type: Number, min: 18, max: 65 }

    trim: 去掉两端空格

    lowercase: true     // 保存前将字符转成小写

    uppercase: true     // 保存前将字符转成大写

    required: true      // 必填

    match:RegExp       // 创建一个正则验证器

    enum:Array         // 检查值是否在给定的数组中

    index: true         // 索引

    unique: true        // 索引,指定字段为独一无二

三、Example

    var schema = new Schema({
        idCard: { type: String, unique: true, trim: true },     // 用户id 字段独一无二、去掉两端空格
        name:    String,            // 可以直接写成String,也可以写成 {type: String}
        binary:  Buffer,
        living:  Boolean,
        updated: { type: Date, default: Date.now }
        age:     { type: Number, min: 18, max: 65 }
        mixed:   Schema.Types.Mixed,
        _someId: Schema.Types.ObjectId,
        array:      [],
        ofString:   [String],
        ofNumber:   [Number],
        ofDates:    [Date],
        ofBuffer:   [Buffer],
        ofBoolean:  [Boolean],
        ofMixed:    [Schema.Types.Mixed],
        ofObjectId: [Schema.Types.ObjectId],
        nested: {
            stuff: { type: String, lowercase: true, trim: true }
        }
    })

Model

具有操作数据库的能力,类似管理数据库的属性和行的类

创建model  mongoose.model('集合名', schema);

    let personScheam = new Scheam({
        name: 'String',
        password: 'String'
    }, {
        timestamps: true,             // 设置timestamps,多加两个字段createdTime、updatedTime,来记录插入时间和更新时间
        collection: 'report_warning_config',
    })

    let personModel = mongoose.model('person', personSchema);

查询

一、find, findById, findOne, or where 

    let TankScheam = new Scheam({
        name: 'String',
        password: 'String'
    })

    let Tank = mongoose.model('Tank', personSchema);

    Tank.find({size: 'samll'}).where('createDate').gt(oneYear).exec(callback);

二、条件查询中常用属性

    $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个元素


三、方法

    1、where('price') - 查询的字段  Tank.find().where('price')

    2、find() - 查询所有,返回的是数组

    3、findOne({name: 'siguang'}) - 只把第一条name为siguang的数据,如果find会将所有都返回

    4、findById(id) - 根据一条id来查找,返回的是一条记录的对象,而不是一个数组,与find({_id: '59bf7ee03f55167fb6cdd75c'})相同

    5、findByIdAndRemove(id) - 根据id查找,并删除这个条数据,如果查找不到返回 null

    6、findByIdAndUpdate(id, update) - 

    7、lean() - Tank.find().lean()      // 默认参数为true, 可以设置 lean(false)

删除

Tank.remove({size: 'large'})

// 查找并删除
Tank.findByAndRemove()

更新

Tank.update({_id: id}, {$set: {size: 'large'}, callback);

// 查找并更新
Tank.findByIdAndUpdate(id, [update]);

Entity

save()

insert和update都需要save(),

egg-mongose 总结

1、问题描述:连接mongoose的过程中遇到mongodb collection自动加s,比如mongo库中有一个userTest集合,如果使用inser会新创建一个userTests

    解决:在创建mode的时候要指定集合名

    module.exports = app => {
        const mongoose = app.mongoose;

        const UserTestSchema = new mongoose.Schema({
            idx: { type: Number },
            password: { type: String }
        });
        return mongoose.model('userTest', UserTestSchema, 'userTest');            // 这里第三个参数要加
    }

1、Model中创建模型

    module.exports = app => {
        const mongoose = app.mongoose;

        const NewsSchema = new mongoose.Schema({
            newsId: { type: Number },
            newsTitle: {type: String, max: 32},
            newsContent: {type: String},
        },{
            timestamps: true,               // 插入记录时会自动创建一个createAt和updateAt时间字段
            collection: 'news',             // mongo中存的collection名
        });

        NewsSchema.index({ 'newsId': 1 });    // newsId为索引

        return mongoose.model('News', NewsSchema);      // News调用时的名
    }

2、在service中调用

    let doc = await app.model.News.find();

3、创建和查询

    const doc = await new app.model.User(user).save();          // 创建时需要new
    const user = await app.model.User.findOne({_id: user._id});     // 查询时不需要new

4、使用find()查询

    如果使用find().lean()返回的是纯javascript对象,而不是mongoose文档,他们没有保存方法

    const resourceTree = await app.model.Resource.find({});

    const resourceTree = await app.model.Resource.find({}).lean();

    返回
    [
        { _id: 5a535142fe6d170e82135e89,
            displayName: '欢欢',
            username: 'huanhuan',
            mobile: 13012309874,
            email: 'huan@126.com' 
        },
        { _id: 5a5357d2bd53b40f791362aa,
            username: 'maolv',
            displayName: '毛驴',
            mobile: 13290984585,
            email: 'maolv@126.com' 
        }
    ]

5、查询条件写法lt

    const password = app.model.UserTest.find().where('idx').lt(5);        // 返回idx字段中小于5的条数

6、更新

    async addChannel(params) {
  const channel = await app.model.ConfigBusinessChannel.findOne({ businessType: params.businessType });
  if (channel) {
    return app.renderBody({
      statusType: app.statusType.recordAlreadyExisted,
    });
  }

  const channelModel = new app.model.ConfigBusinessChannel({
    businessType: params.businessType, // 业务渠道ID
    businessName: params.businessName, // 业务渠道名
    isEnabled: params.isEnabled, // 是否启用
    paySignedCompanys: [], // 签约的结算主体
  });
  await channelModel.save();

  const response = app.renderBody({
    statusType: app.statusType.success,
    data: {},
  });

  return response;
}

| https://mongoose.shujuwajue.com/guide/schemas.html // 中文API
| http://www.nodeclass.com/api/mongoose.html
| https://github.com/eggjs/egg-mongoose egg-mongoose
| http://cnodejs.org/topic/504b4924e2b84515770103dd
| http://www.cnblogs.com/xuange306/p/4603551.html
| http://www.cnblogs.com/winyh/p/6682039.html
| http://cnodejs.org/topic/504b4924e2b84515770103dd
| http://www.hubwiz.com/class/543b2e7788dba02718b5a4bd