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.9 附言
Schema
不仅定义了文档结构
和使用性能
,还可以有扩展插件
、实例方法
、静态方法
、复合索引
、文档生命周期钩子
Schema
可以定义插件,并且插件具有良好的可拔插性,请有兴趣的读者继续往后阅读或者查阅官方资料。
2. Schema的扩展
2.1 实例方法
有的时候,我们创造的Schema
不仅要为后面的Model
和Entity
提供公共的属性,还要提供公共的方法。
下面例子比快速通道的例子更加高级,可以进行高级扩展:
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 PersonModel({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.3 索引
索引或者复合索引能让搜索更加高效,默认索引就是主键索引ObjectId
,属性名为_id
, 索引会作为一个专题来讲解
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;
});
那么就能用krouky.name.full
来调用全名了,反之如果知道full,也可以反解first
和last
属性
PersonSchema.virtual(‘name.full’).set(function(name){
var split = name.split(’ ');
this.name.first = split[0];
this.name.last = split[1];
});
var PersonModel = mongoose.model(‘Person’,PersonSchema);
var krouky = new PersonModel({});
krouky.name.full = ‘krouky han’;//会被自动分解
console.log(krouky.name.first);//krouky
2.5 配置项
在使用new Schema(config)
时,我们可以追加一个参数options
来配置Schema
的配置,形如:
var ExampleSchema = new Schema(config,options);
或者使用
var ExampleSchema = new Schema(config);
ExampleSchema.set(option,value);
可供配置项有:safe
、strict
、capped
、versionKey
、autoIndex
2.5.1 safe——安全属性(默认安全)
一般可做如下配置:
new Schema({…},{safe:true});
当然我们也可以这样
new Schema({…},{safe:{j:1,w:2,wtimeout:10000}});
j
表示做1份日志,w
表示做2个副本(尚不明确),超时时间10秒
2.5.2 strict——严格配置(默认启用)
确保Entity
的值存入数据库前会被自动验证,如果你没有充足的理由,请不要停用,例子:
var ThingSchema = new Schema({a:String});
var ThingModel = db.model(‘Thing’,SchemaSchema);
var thing = new Thing({iAmNotInTheThingSchema:true});
thing.save();//iAmNotInTheThingSchema这个属性将无法被存储
如果取消严格选项,iAmNotInTheThingSchema
将会被存入数据库
该选项也可以在构造实例时使用,例如:
var ThingModel = db.model(‘Thing’);
var thing1 = new ThingModel(doc,true); //启用严格
var thing2 = new ThingModel(doc,false); //禁用严格
注意:
strict
也可以设置为throw
,表示出现问题将会抛出错误
2.5.3 shardKey
需要mongodb
做分布式,才会使用该属性
2.5.4 capped——上限设置
如果有数据库的批量操作,该属性能限制一次操作的量,例如:
new Schema({…},{capped:1024}); //一次操作上线1024条数据
当然该参数也可是JSON对象,包含size、max、autiIndexId属性
new Schema({…},{capped:{size:1024,max:100,autoIndexId:true}});
2.5.5 versionKey——版本锁
版本锁是Mongoose
默认配置(__v属性)的,如果你想自己定制,如下:
new Schema({…},{versionKey:‘__someElse’});
此时存入数据库的版本锁就不是__v
属性,而是__someElse
,相当于是给版本锁取名字。
具体怎么存入都是由Mongoose
和MongoDB
自己决定,当然,这个属性你也可以去除
new Schema({…},{versionKey:false});
除非你知道你在做什么,并且你知道这样做的后果
2.5.6 autoIndex——自动索引
该内容将在索引章节单独讲解
3. Documents
Document
是与MongoDB
文档一一对应的模型,Document
可等同于Entity
,具有属性和操作性
注意:
Document
的`CRUD都必须经过严格验证的,参看2.5.2 Schema的strict严格配置
3.1 查询
查询内容过多,专题讲解
3.2 更新
有许多方式来更新文件,以下是常用的传统方式:
PersonModel.findById(id,function(err,person){
person.name = ‘MDragon’;
person.save(function(err){});
});
这里,利用Model
模型查询到了person
对象,该对象属于Entity
,可以有save操作,如果使用
Model`操作,需注意:
PersonModel.findById(id,function(err,person){
person.name = ‘MDragon’;
var _id = person._id; //需要取出主键_id
delete person._id; //再将其删除
PersonModel.update({_id:_id},person,function(err){});
//此时才能用Model操作,否则报错
});
update
第一个参数是查询条件,第二个参数是更新的对象,但不能更新主键,这就是为什么要删除主键的原因。
当然这样的更新很麻烦,可以使用$set
属性来配置,这样也不用先查询,如果更新的数据比较少,可用性还是很好的:
PersonModel.update({_id:_id},{$set:{name:‘MDragon’}},function(err){});
需要注意,Document
的CRUD
操作都是异步执行,callback
第一个参数必须是err
,而第二个参数各个方法不一样,update
的callback
第二个参数是更新的数量,如果要返回更新后的对象,则要使用如下方法
Person.findByIdAndUpdate(_id,{$set:{name:‘MDragon’}},function(err,person){
console.log(person.name); //MDragon
});
类似的方法还有findByIdAndRemove
,如同名字,只能根据id查询并作update
/remove
操作,操作的数据仅一条
3.3 新增
如果是Entity
,使用save
方法,如果是Model
,使用create
方法
//使用Entity来增加一条数据
var krouky = new PersonModel({name:‘krouky’});
krouky.save(callback);
//使用Model来增加一条数据
var MDragon = {name:‘MDragon’};
PersonModel.create(MDragon,callback);
两种新增方法区别在于,如果使用Model
新增时,传入的对象只能是纯净的JSON
对象,不能是由Model
创建的实体,原因是:由Model
创建的实体krouky
虽然打印是只有{name:'krouky'}
,但是krouky
属于Entity
,包含有Schema
属性和Model
数据库行为模型。如果是使用Model
创建的对象,传入时一定会将隐藏属性也存入数据库,虽然3.x
追加了默认严格属性,但也不必要增加操作的报错
3.4 删除
和新增一样,删除也有2种方式,但Entity
和Model
都使用remove
方法
4.Sub Docs
如同SQL
数据库中2张表有主外关系,Mongoose
将2个Document
的嵌套叫做Sub-Docs
(子文档)
简单的说就是一个Document
嵌套另外一个Document
或者Documents
:
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数前端工程师,想要提升技能,往往是自己摸索成长或者是报班学习,但对于培训机构动则几千的学费,着实压力不小。自己不成体系的自学效果低效又漫长,而且极易碰到天花板技术停滞不前!
因此收集整理了一份《2024年Web前端开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上前端开发知识点,真正体系化!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新
如果你觉得这些内容对你有帮助,可以添加V获取:vip1024c (备注前端)
最后
除了简历做到位,面试题也必不可少,整理了些题目,前面有117道汇总的面试到的题目,后面包括了HTML、CSS、JS、ES6、vue、微信小程序、项目类问题、笔试编程类题等专题。
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算
面有117道汇总的面试到的题目,后面包括了HTML、CSS、JS、ES6、vue、微信小程序、项目类问题、笔试编程类题等专题。
一个人可以走的很快,但一群人才能走的更远。如果你从事以下工作或对以下感兴趣,欢迎戳这里加入程序员的圈子,让我们一起学习成长!
AI人工智能、Android移动开发、AIGC大模型、C C#、Go语言、Java、Linux运维、云计算、MySQL、PMP、网络安全、Python爬虫、UE5、UI设计、Unity3D、Web前端开发、产品经理、车载开发、大数据、鸿蒙、计算机网络、嵌入式物联网、软件测试、数据结构与算法、音视频开发、Flutter、IOS开发、PHP开发、.NET、安卓逆向、云计算