目录
1. mongoose简介
mongoose是基于Node.js的用于操作MongoDB数据库的第三方的模块
mongoose库简而言之就是在node环境操作MongoDB数据库的一种便捷的封装,一种对象模型工具,Mongoose将数据库中的数据转换为JavaScript对象以供你在应用中使用.
Mongooose中,有三个比较重要的概念,分别是Schema、Model、Document。它们的关系是:Schema生成Model,Model创造Document,Model和Document都可对数据库操作造成影响,但Model比Document更具操作性
Schema
用于定义数据库的结构。类似创建表时的数据定义(不仅仅可以定义文档的结构和属性,还可以定义文档的实例方法、静态模型方法、复合索引等),每个Schema
会映射到mongodb中的一个collection,Schema
不具备操作数据库的能力Model是由Schema编译而成的构造器,具有抽象属性和行为,可以对数据库进行增删查改。Model的每一个实例(instance)就是一个文档document
Document是由Model创建的实体,它的操作也会影响数据库
2. mongoose的使用方法简单介绍
1.引入mongoose mongoose 就是一个实例,这个实例身上有很多的方法;
const mongoose = require('mongoose');
2. 连接数据库(在这里我连接的是student数据库)
mongoose.connect("mongodb://localhost/student");
3.创建骨架Schema(定义字段)
一个集合就是一个骨架,所以骨架不止一个
let Schema = new mongoose.Schema({
name:String,
age:Number,
sex:String
})
4. 创建模型(类),用于操作数据库
const Student = mongoose.model("student",Schema)
5. 创建实例(实例化类),用于向数据库中增加数据
const user= new Student({
name:"hongyu",
age:18,
sex:'女',
});
6. 保存对象
user.save()
7. 补充数据库操作
// 增加 user.save()
// 删除 user.findById( _id, ( err,data) => { data.remove() })
// 修改 user.findById( _id, ( err,data) => { data.name = xxx, data.save() })
// 查询 user.find({},( err,data) => { })
3. 详细解释mongoose的使用方法的每个部分
3.1 连接数据库
//引入mongoose
const mongoose = require('mongoose');
//链接数据库
mongoose.connect("mongodb://localhost/student");
按照我们的理解连接数据库上面的操作应该是不会有错误的,但是事实上不是的哦,如果我们这样直接连接数据库,会有下面的报错信息:
ecationWarning: current URL string parser is deprecated, and will be removed in a future version. To use the new parser, pass option { useNewUrlParser: true } to MongoClient.connect.
(node:12712) DeprecationWarning: current Server Discovery and Monitoring engine is deprecated, and will be removed in a future version. To use the new Server Discover and Monitoring engine, pass option { useUnifiedTopology: true } to the MongoClient constructor.
我们就需要在连接数据库的时候进行下面的配置(报错信息里有给我们提示,已经标红,所以我们也不需要可以的记住如何进行配置):
//引入mongoose
const mongoose = require('mongoose');
//链接数据库
mongoose.connect("mongodb://localhost/student",{
useUnifiedTopology: true ,
useNewUrlParser: true
},function (err) {
if(err) {
throw err;
}else{
console.log('数据库连接成功');
}
});
3.2 创建schema
Schema主要用于定义MongoDB中集合Collection里文档document的结构
定义Schema非常简单,指定字段名和类型即可,支持的类型包括以下8种
- String 字符串
- Number 数字
- Date 日期
- Buffer 二进制
- Boolean 布尔值
- Mixed 混合类型
- ObjectId 对象ID
- Array 数组
3.2.1 定义schema
每个 schema 都会映射到一个 MongoDB collection ,并定义这个collection里的文档的构成。
var schema = new mongoose.Schema({
字段名: 类型,
字段名: 类型,
....
})
例如:
let Schema = new mongoose.Schema({
name:String,
age:Number,
sex:String
})
在我们向数据库中存入数据的时候,存入的数据类型要和Schema限定的类型相同,如果不同弄,就会发生隐式类型转换,如果转换不了就会报错.
3.2.2 schema中设置默认值
如果需要指定默认值,那么Schema中的字段值将不再是类型,而是一个对象
对象的
type
属性为字段类型,default
为默认值
//设置年龄的默认值为18,性别的默认值为男
const Schema = new mongoose.Schema({
username:String,
age:{
type:Number,
default: 18
},
sex:{
type:String,
default:"男"
}
})
除了使用固定值作为默认值外,还可以使用动态值作为默认值例如时间
3.2.3 验证器
所有数据类型都有的验证器
required
,有配置required
验证器的字段为必须的.
- 数字类型特有的验证器
max
,min;max
,min
验证用户传递的数字的最大最小值.- 字符串枚举验证器
enum;enum
验证器就是验证用户输入的字符串,是不是在enum
中罗列的字段,否则机会报错- 字符串正则验证
match;match
验证器的值是一个正则,验证用户输入的是否通过正则匹配- 自定义验证器
validate:validate
自定义验证器的值是一个函数, 返回一个布尔值,true
为验证通过,false
为验证不通过
let Schema = new mongoose.Schema({
name: {
type: String,
trim:true, //自动删除输入姓名中的空格
},
age:{
type:Number,
// default:18, //设置默认值(静态)
required:true,
max:60, //年龄的最大值为60
min:18, //年龄的嘴小值为18
},
sex:String,
email:{
type:String,
match: /(.+)@(.+)\.["com"| "cn"]/g, //正则匹配
},
status: {
type:String,
enum:['success','false'], //输入的字符串只能是seccessfalse
}
})
3.2.4 版本问题
我们会发现,当我们想数据库中欧冠保存诗句之后,保存的数据会默认带有一个_v属性:
这个属性是默认的,如果我们不设置的话就会自动为我们生成,如果不想要这个属性,我们可以在定义Schema的时候进行如下的设置:
let UserSchema = mongoose.Schema({
name:String,
age:Number,
sex:String,
},{versionKey:false})
3.3 根据schema模型创建model
模型是根据Schema创建出来的构造器,具备操作数据库的能力
我们在使用Mongoose的时候,一定要记住,一个mongoose的model就对应一个集合,创建一个model的时候,就是使用mongoose.model()
const student = mongoose.model("模型名称",Schema,"集合名称")
集合名称与模型名称保持一致,通常我们不传第三个参数
const student = mongoose.model("集合的名字",Schema)
如果我们在这里传入一个本身不存在的集合名,那么就会默认为我们创建一个集合.
3.4 根据模型创建实例
当我们创建完模型之后就可以通过模型来创建实例,实例具备数据库操作能力,通常用于写数据(新增,修改,删除),会影响数据库的操作
const user= new Student({
name:"hongyu",
age:18,
sex:'女',
});
//保存数据
user.save()
4. 数据库操作(增删改查)
在这之前建议先了解一下mongodb数据库的增删改查操作,戳链接即可https://blog.csdn.net/lhrdlp/article/details/106046874
4.1 查询文档
find()方法:根据条件对象进行数据查询,可以找到多条数据
模型.find({条件},function(err,data){
// data 是从 数据库中读取的数据
// find()方法查询出来的数据一定是一个数组,即使没有数据也是一个空数组
})
findOne() 方法: 查询符合条件查询一条数据
模型.findOne({条件},function(err,data){
// data 是从数据库中读取的数据
// find()方法查询出来的数据是一个单个的文档对象
})
findById()查询一条数据(通过ID找指定的数据)
模型.findById("id",function(err,data){
// findById 找出来的数据是一个对象,因为只是找一个数据
})
exec()另一种常用的写法(为了更好的实现链式调用)
模型.find(()).exec(function(err,data){
})
例子:
//查询结果是数组
student.find({$or:[{age:25},{name:'小刚'}]})
.then(result=> {
console.log(result)
}).catch(err=> {
console.log(err);
});
//查询结果是数组
//[
// {
// _id: 5eba06adb77f1c2a18a1192b,
// name: '小刚',
// age: 16,
// sex: '男',
// __v: 0
// },
// {
// _id: 5eba0e4be9dbed1af09fe8b8,
// name: '小明',
// age: 25,
// sex: '男',
// __v: 0
// }
// ]
//查询符合条件的第一条数据
student.findOne({age:21})
.then(result=> {
console.log(result)
}).catch(err=> {
console.log(err);
});
//结果是一个文档对象
//{
// _id: 5eba165323935527cc4af552,
// age: 21,
// time: 1589253715157,
// name: 'ym,
// sex: '女',
// __v: 0
// }
//通过id查询数据
// findById 找出来的数据是一个对象,因为只是找一个数据
student.findById('5eba0f32cc744e0658091d9f',function (err,data) {
if(err) {
console.log(err);
}
console.log(data);
})
//{
// _id: 5eba165323935527cc4af552,
// age: 21,
// time: 1589253715157,
// name: 'ym',
// sex: '女',
// __v: 0
// }
4.2 增加文档
实例.属性名= 属性值
....
实例.save(function(err){ // 将数据保存到数据库中
// err 数据保存失败
})
例子:
const why= new Student({
name:"hongyu",
age:18,
sex:'女',
});
why.save().then(result=>{
console.log(result)
}).catch(err=> {
console.log(err);
})
4.3 修改数据
简单来说,修改数据需要两个步骤:
找出需要修改的数据
将数据修改以后保存会数据库
模型.findById("id").exec(function(err,data){
// 如果没有报错,就是先查询到指定的数据data
// 然后修改数据
data.name = "新的值";
data.age = "新的值";
data.save(function(err){
// err在修改错误时报错有值
})
})
例子:
student.findById('5eba0f32cc744e0658091d9f')
.then(result=> {
//console.log(result);
result.name = "朱莉";
result.age = 29;
result.save()
.then(data=> {
console.log(data);
}).catch(err=> {
console.log(err);
})
}).catch(err=> {
console.log(err);
})
4.4 删除数据
删除数据的步骤如下:
先查询到要被删除的数据
调用remove()方法删除数据
模型.findById("id").exec(function(err,data){
// 如果没有报错,就是先查询到指定的数据data
// 然后删除数据
data.remove(function(err,data){
// err在数据删除失败后会有值
// data是删除的数据
})
})
例子:
student.findById('5eba0f32cc744e0658091d9f')
.then(data=> {
console.log(data);
data.remove()
.then(data=> {
console.log('数据删除成功');
}).catch(err=> {
console.log('数据删除失败')
})
}).catch(err=> {
console.log(err);
})
5. Mongoose静态方法和动态方法(自定义方法)
5.1 静态方法
静态方法通过schema上的statics属性定义
静态方法定义在Schema上,在定义mongoose.model类后,通过这个类来调用这个静态方法
静态方法中的this指的就是当前这个集合,可以通过find()查找
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/student',{
useUnifiedTopology: true ,
useNewUrlParser: true
});
//定义scheme
let UserSchema = mongoose.Schema({
name:String,
age:Number,
sex:String,
},{versionKey:false})
// 静态方法通过Schema上的statics属性定义
UserSchema.statics.findByAge = function(age) {
console.log(this); //Model { students } 静态方法中的this指代这个数据集合,就是students
this.find({age},(err,data)=>{
if(err) {
console.log(err);
}
console.log(data);
})
}
//创建一个类
let User = mongoose.model("students",UserSchema);
//静态方法调用
User.findByAge(22);
我们可以通过静态方法修改数据:
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/student',{
useUnifiedTopology: true ,
useNewUrlParser: true
});
//定义scheme
let UserSchema = mongoose.Schema({
name:String,
age:Number,
sex:String,
},{versionKey:false})
// 静态方法通过Schema上的statics属性定义
UserSchema.statics.findByAge = function(age) {
console.log(this); //Model { students } 静态方法中的this指代这个数据集合,就是students
this.find({age},(err,data)=>{
if(err) {
console.log(err);
}
console.log(data);
})
}
//通过静态方法去修改数据
UserSchema.statics.ChangeAgeByName = function(name) {
this.find({name},(err,data)=> {
let result = data[0];
// console.log(result)
if(err) {
console.log(err)
}
if(result.sex == "男") {
result.sex = "女";
}else {
result.sex = "男";
}
result.save();
})
}
//创建一个类
let User = mongoose.model("students",UserSchema);
User.ChangeAgeByName('大刘');
5.2 动态方法
动态方式是通过Schema上的 methods方法定义
无论静态方法还是动态方法都是定义在Schema上面,只是调用的主体不同,静态方法的调用主体是类,动态方法的调用主体是实例
其实静态方法中返回的result数组中就是实例,所有我们要使用动态方法可以先使用静态方法通过回调拿到对应的实例以后在使用动态方法
const mongoose = require('mongoose');
mongoose.connect('mongodb://localhost/student',{
useUnifiedTopology: true ,
useNewUrlParser: true
});
//定义scheme
let UserSchema = mongoose.Schema({
name:String,
age:Number,
sex:String,
},{versionKey:false})
// 静态方法通过Schema上的statics属性定义
UserSchema.statics.findByAge = function(age,callback) {
console.log(this); //Model { students } 静态方法中的this指代这个数据集合,就是students
this.find({age},(err,data)=>{
//返回查询到的数据
callback(data);
})
}
//定义动态方法
UserSchema.methods.fun = function(){
console.log(`哈喽,我的名字是${this.name},我今年${this.age}岁了`);
}
//创建一个类
let User = mongoose.model("students",UserSchema);
//先调用静态方法找到数据
User.findByAge(22,function (result) {
console.log(result);
let user = result[0];
user.fun();
})
mongoose中如果要查询数据,一般来说使用静态方法,如果要改变值,直接对象打点更改属性,然后save就可以了
可以理解静态方法是操作集合,动态方法是操作某一个文档的
简单的对两个方法做个对比,具体的可以通过上面的两个例子来理解.
方法 | 静态 | 动态 |
定义 | Schema上的statics属性定义 | Schema上的method属性定义 |
调用主体 | 类可以调用 | 实例能够调用 |
适用场景 | 操作集合 | 操作文档 |