mongoose的基础知识

一、快速通道

1.1 名词解释
Schema : 一种以文件形式存储的数据库模型骨架,不具备数据库的操作能力
Model : 由Schema发布生成的模型,具有抽象属性和行为的数据库操作对
Entity : 由Model创建的实体,他的操作也会影响数据库
1.本学习文档采用严格命名方式来区别不同对象,例如:

```
   var PersonSchema;   //Person的文本属性
    var PersonModel;    //Person的数据库模型
    var PersonEntity;   //Person实体

Schema、Model、Entity的关系请牢记,Schema生成Model,Model创造Entity,Model和Entity都可对数据库操作造成影响,但Model比Entity更具操作性。、

二、使用mongoose的步骤

1.首先你必须安装MongoDB和NodeJS

2.在项目只能够创建一个数据库连接,如下:

var mongoose = require('mongoose');    //引用mongoose模块
var db = mongoose.createConnection('localhost','test'); //创建一个数据库连接

3.打开本机localhost的test数据库时,我们可以监测是否有异常

db.on('error',console.error.bind(console,'连接错误:'));
db.once('open',function(){
  //一次打开记录
});

注意:

成功开启数据库后,就可以执行数据库相应操作,假设以下代码都在回调中处理

4.定义一个Schema

var PersonSchema = new mongoose.Schema({
  name:String   //定义一个属性name,类型为String
});

5.将该Schema发布为Model

var PersonModel = db.model('Person',PersonSchema);
//如果该Model已经发布,则可以直接通过名字索引到,如下:
//var PersonModel = db.model('Person');
//如果没有发布,上一段代码将会异常

6.用Model创建Entity

var personEntity = new PersonModel({name:'Krouky'});
//打印这个实体的名字看看
console.log(personEntity.name); //Krouky

7.我们甚至可以为此Schema创建方法

//为Schema模型追加speak方法
PersonSchema.methos.speak = function(){
  console.log('我的名字叫'+this.name);
}
var PersonModel = db.model('Person',PersonSchema);
var personEntity = new PersonModel({name:'Krouky'});
personEntity.speak();//我的名字叫Krouky

8.Entity是具有具体的数据库操作CRUD的

personEntity.save();  //执行完成后,数据库就有该数据了

9.如果要执行查询,需要依赖Model,当然Entity也是可以做到的

PersonModel.find(function(err,persons){
  //查询到的所有person
});

Model和Entity都有能影响数据库的操作,但仍有区别,后面我们也会做解释
1.2如何定义Schema

  var BlogSchema = new Schema({
      title:String,
      author:String
      //new Schema()中传入一个JSON对象,该对象形如 xxx:yyyy ,
      /xxx是一个字符串,定义了属性,yyy是一个Schema.Type,定义了属性类型
    });

1.3 什么是Schema.Type
Schema.Type是由Mongoose内定的一些数据类型,基本数据类型都在其中,他也内置了一些Mongoose特有的Schema.Type。当然,你也可以自定义Schema.Type,只有满足Schema.Type的类型才能定义在Schema内。

   //举例:
    var ExampleSchema = new Schema({
      name:String,
      binary:Buffer,
      living:Boolean,
      updated:Date,
      age:Number,
      mixed:Schema.Types.Mixed, //该混合类型等同于nested
      _id:Schema.Types.ObjectId,  //主键
      _fk:Schema.Types.ObjectId,  //外键
      array:[],
      arrOfString:[String],
      arrOfNumber:[Number],
      arrOfDate:[Date],
      arrOfBuffer:[Buffer],
      arrOfBoolean:[Boolean],
      arrOfMixed:[Schema.Types.Mixed],
      arrOfObjectId:[Schema.Types.ObjectId]
      nested:{
        stuff:String,
      }
    });

1.5 关于Buffer

Buffer和ArrayBuffer是Nodejs两种隐藏的对象,相关内容请查看NodeJS-API
1.6 关于Mixed

Schema.Types.Mixed是Mongoose定义个混合类型,该混合类型如果未定义具体形式。因此,如果定义具体内容,就直接使用{}来定义,以下两句等价
1.7 关于ObjectId

主键,一种特殊而且非常重要的类型,每个Schema都会默认配置这个属性,属性名为_id,除非自己定义,方可覆盖

   var mongoose = require('mongoose');
    var ObjectId = mongoose.Schema.Types.ObjectId;
    var StudentSchema = new Schema({}); //默认会有_id:ObjectId
    var TeacherSchema = new Schema({id:ObjectId});//只有id:ObjectId

该类型的值由系统自己生成,从某种意义上几乎不会重复,生成过程比较复杂,有兴趣的朋友可以查看源码。
1.8 关于Array

Array在JavaScript编程语言中并不是数组,而是集合,因此里面可以存入不同的值,以下代码等价:

  var ExampleSchema1 = new Schema({array:[]});
    var ExampleSchema2 = new Schema({array:Array});
    var ExampleSchema3 = new Schema({array:[Schema.Types.Mixed]});
    var ExampleSchema4 = new Schema({array:[{}]});
  1. Schema的扩展
 var PersonSchema = new Schema({name:String,type:String});
    //查询类似数据
    PersonSchema.methods.findSimilarTypes = function(cb){
      return this.model('Person').find({type:this.type},cb);
    }
    var PersonModel = mongoose.model('Person',PersonSchema);
    var krouky = new PersonSchema({name:'krouky',type:'前端工程师'});
    krouky.findSimilarTypes(function(err,persons){
      //persons中就能查询到其他前端工程师
    });

2.2 静态方法

静态方法在Model层就能使用,如下:

 PersonSchema.statics.findByName = function(name,cb){
    this.find({name:new RegExp(name,'i'),cb});
  }
  var PersonModel = mongoose.model('Person',PersonSchema);
  PersonModel.findByName('krouky',function(err,persons){
    //找到所有名字叫krouky的人
  });

2.4 虚拟属性
Schema中如果定义了虚拟属性,那么该属性将不写入数据库

  var PersonSchema = new Schema({
      name:{
        first:String,
        last:String
      }
    });
var PersonModel =mongoose.model('Person',PersonSchema);
    var krouky = new PersonModel({
      name:{first:'krouky',last:'han'}
    });

如果每次想使用全名就得这样

console.log(krouky.name.first + ' ' +krouky.name.last);

显然这是很麻烦的,我们可以定义虚拟属性:

PersonSchema.virtual('name.full').get(function(){
      return this.name.first + ' ' + this.name.last;
    });

三、查询语言系统

1、查询选择系统

最简单的查询语句,实现的是向数据库中插入20条数据

for(var i=1;i<11;i++)
{db.customers.insert({id:i,name:"小傲冥",age:100+i})}

找到对应的文档

db.customers.find({id:9})

为了精确的匹配选择器,条件可以是多个

db.customers.find({id:9,age:109})

带条件的查询

db.customers.find({age:{$lt:109}})

返回的是年龄小于109 的customer
lte gt大于 gte in key值在某些value的 $nin key值不在某些value的

db.customers.find({age:{$in:[103,105]}})

$or表示的是或运算选择器

db.customers.find({$or:[{id:1},{age:109}]})

$and表示的是与运算器

db.customers.find({$and:[{id:1},{age:109}]})

2、查询投射

查询选择器用来指定返回匹配的文档,有事我们需要对返回的结果进行进一步的处理,这时就使用到了查询投射
查询出来所有的字段并且对id字段进行排序

db.customers.find({}).sort({id:-1})

跳过10行,从这个位置返回接下来的5行,并且按id进行排序

db.customers.find({}).skip(5).limit(3).sort({id:-1})

3、数组操作
插入一个嵌套有数组的文档

db.customers.insert(
   {"id":1,
       "sta":[
           {"sid":1,
           "dec":"取消"},
           {
               "sid":2,
           "dec":"已付款"}
       ]
    })

四、索引与查询优化

mongoDB的索引的数据结构也是B+树,利用索引可以减少文档的扫描数量
单字段索引
建立一个唯一索引

db.customers.ensureIndex({name:1},{unique:true})

建立一个普通索引

db.customers.ensureIndex({name:1})

使用索引进行查询

db.customers.find({name:"aa9"}).explain()

演示索引的优点

for(var i=0;i<10;i++){
    db.customers.insert({name:"aa"+i,country:"bb"})
    }

使用索引,只会查找一篇文档

db.customers.find({"name":"aa9"}).explain()
db.customers.find({"country":"bb"}).explain()

没有使用索引、会查找所有的文档
复合索引
创建一个复合索引

db.customers.ensureIndex({name:1,country:1})

五、增删改操作

1、插入语句

db.customer.insert({name:"gyw",mobile:"1051743154"})

检测插入是成功

db.customer.find()

注意的是:不需要预先创建一个集合,插入时数据会自动创建,每一次创建的文档的_id都是必须唯一的,重复插入会引起错误
2、修改语句
由update来完成,mongo里边的修改分为两种
1、针对具体的目标字段
2、取代性的改变
update语句的语法格式:
db.collection.update({query,update,,})
query参数是一个查询器
update参数为需要修改的地方,若这个选项没有值的话,发生的就是取代性的变化
upsert 是一个可选参数 boolean 默认为false
为true的时候,当在记录没有找到匹配的时候会插入到文档的末尾。
multi 是一个可选参数 boolean 默认为false
为true的时候,当在记录中找到多条的记录的时候就会发生多条记录的替换,
演更新的操作

db.price.insert({name:"apple","price":3000})

实现更新的操作
1、更该指定的字段 name改为apple5s price加400

db.price.update({name:"apple"},{$set:{name:"apple5s"},$inc:{price:400}})

2、更改指定字段,其他字段被清除掉

db.price.update({name:"apple5s"},{name:"appleshausa"})

3、更改多个文档中的指定字段

db.price.update({name:"apple"},{$set:{price:5000}},{multi:true})

4、找不到文档时做插入的操作

db.price.update({name:"appleqwq"},{$set:{price:5000}},{upsert:true})

删除语句
mongoDB中的删除remove也是数据库CRUD操作中的一种最基本的操作
remove
格式:db.cllection.remove(,)
query:可选参数 类似于sql语句的where
justOne:可选参数 boolean 表示是否只是删除第一个,
remove()方法没有参数的时候表示删除所有的文档,氮素不会删除这个文档对应的索引。要删除集合的索引,使用的是drop方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值