mongoose安装和使用(超详细)
Mongoose 是一个让我们可以通过Node来操作MongoDB数据库的一个模块Mongoose 是一个对象文档模型(ODM)库,它是对Node原生的MongoDB模块进行了进一步的优化封装大多数情况下,他被用来把结构化的模式应用到一个MongoDB集合,并提供了验证和类型装换等好处基于MongoDB驱动,通过关系型数据库的思想来实现非关系型数据库。
一.简介
介绍
-
Mongoose 是一个让我们可以通过Node来操作MongoDB数据库的一个模块
-
Mongoose 是一个对象文档模型(ODM)库,它是对Node原生的MongoDB模块进行了进一步的优化封装
-
大多数情况下,他被用来把结构化的模式应用到一个MongoDB集合,并提供了验证和类型装换等好处
-
基于MongoDB驱动,通过关系型数据库的思想来实现非关系型数据库
优势/好处
-
为文档创建模式结构(Schema),也可以说是约束
-
对模型中的对象/文档进行验证
-
数据可以通过类型装换装换为对象模型
-
可以使用中间件来应用业务逻辑挂钩
-
相比MongoDB驱动更容易
new Object
Schema(模式对象)
——Schema 对象定义约束了数据库中的文档结构
Model
——Model 对象作为集合中的所有文档的表示,相当于MongoDB中的collection,它的每一个实例就是一个document文档
Document
——Document表示集合中的具体文档,相当于collection中的一个具体文档
关系:Schema生成Model,Model创造Document
模式(Schemas)
-
每个 schema 都会映射到一个 MongoDB collection 并定义这个collection里的文档结构
-
创建一个 schema 对象
const mongoose = require('mongoose')
//调用 Schema
const Scheme = mongoose.Schema//创建 schema 对象
var stuSchema = new Schema({
name: String,
age: Number,
gender:{
type: String,
default:'male' //定义默认类型
},
addr: String
})
-
在Schema定以后添加字段时需要使用 add() 方法
var stuSchema = new Schema({
{...},
{ timestamps:true }
})
【_id】
当未定义_id
字段时 mongoose 会为每一个文档自动添加一个不重复的_id
,类型为ObiectId(在查询语句中需要通过 findById() 才能查询)
二.安装使用mongoose
前提:安装MongoDB,Nodejs
1.下载安装Mongoose
npm i mongoose
2.项目中引入mongoose
var mongoose = require(‘mongoose’)
3.连接数据库
mongoose.connect(‘mongodb://数据库ip地址 : 端口号( 默认端口27017可以省略 )/数据库名’)
数据库连接成功事件
补充
将成功回调的on改成once
事件回调函数只执行一次
mongoose.connection.once(‘open’ , () => {})
数据库断开事件
mongoose.connection.once(‘close’ , () => {})
4.创建Schema(模式)对象
var stuSchema = new Schema({})
-
通过
Schema
创建Model
-
Model 代表的是数据库中的集合,通过Model才能对数据库进行操作
5.映射
var stuModel = mongoose.model(‘student’,stuSchema)
参数
-
要映射的集合名
-
创建的约束(Schema对象)
6.通过映射返回的值对数据库进行增、删、改、查
7.断开数据库连接(一般不使用)
const mongoose = require('mongoose');
// 连接数据库
mongoose.connect('mongodb://127.0.0.1:27017/user');// 设置连接成功的回调
mongoose.connection.once('open', () => {
if (mongoose.connection.readyState === 1) {
console.log("连接成功");// 创建文档的结构对象
let BookSchema = new mongoose.Schema({
name: {
type: String,
required: true
},
author: String,
price: Number
});// 创建模型对象
let BookModel = mongoose.model('books', BookSchema);// 数据插入
BookModel.create(
{
name: '西游记',
author: '哈哈',
price: 19.9,
},
{
name: '红楼梦',
author: '曹雪芹',
price: 19.9,
},
{
name: '水浒传',
author: '111',
price: 19.9,
},
{
name: '三国演义',
author: '2222',
price: 19.9,
},
(err, data) => {
if (err) {
console.log(err);
return;
}
console.log(data);
// 插入数据后关闭连接
mongoose.disconnect();
}
);
// 数据删除
// BookModel.remove({name:/西游记/},function(err){})
}
});// 设置连接错误的回调
mongoose.connection.on('error', () => {
console.log("连接失败");
});// 设置连接关闭的回调
mongoose.connection.on('close', () => {
console.log("连接关闭");
});
创建文档的结构对象
设置集合中文档的属性以及属性值的类型
Let BookSchema= new mongoose.Schema({
name: String
author: String;
price:Number
})
创建模型对象 对稳定操作的封装对象
Let BookModel= mongoose.model( ' books ',BookSchema)
集合名称,结构对象
文档新增
create()
-
操作模型
-
Model.create(doc(s), [callback])
-
参数:
[doc(s)]:文档对象或文档对象数组
[callback]:回调函数
// 数据插入
stuModel.create({name:"小明",grades:68},{name:"小红",grades:80},(err,doc1,doc2) => {
if(!err){
console.log(doc1)
//{ _id: 6017be2d77c8dd01242624bb, name: '小明', grades: 68, __v: 0 }
console.log(doc2)
//{ _id: 6017be2d77c8dd01242624bc, name: '小红', grades: 80, __v: 0 }
}
})
save()
-
操作的是文档
-
Model.prototype.save([options], [options.safe], [options.validateBeforeSave], [fn])
//链式调用 通过new 一个Model创建一个 document
new stuModel({name:"小明",grades:68}).save((err,docs) => {
if(!err){
console.log(docs)
//{ _id: 6017bd1cf4cc8544d8ed2a8a, name: '小明', grades: 68, __v: 0 }
}
})
insertMany()
-
Model.insertMany(doc(s), [options], [callback])
-
返回值为一个数组
//链式调用 通过new 一个Model创建一个 document
stuModel.insertMany({name:"小明",grades:68},{name:"小芳",grades:94},(err,docs) => {
if(!err){
console.log(docs)
/*[{ _id: 6017befb5c36d64d08b72576, name: '小明', grades: 68, __v: 0 },
{ _id: 6017befb5c36d64d08b72577, name: '小芳', grades: 94, __v: 0 }]*/
}
})
文档查询
【find()】
-
Model.find(conditions, [projection], [options], [callback])
-
参数
conditions:查询条件
[projection]:控制返回字段
[options]:配置查询参数
[callback]:回调函数–function(err,docs){}
// 数据查询
// BookModel.find((err, docs) => {
// if (!err) {
// console.log(docs)
// }
// })
findById()
Model.findById(conditions, [fields], [options], [callback])
var mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',(err) => {
if(!err){
var schema = new mongoose.Schema({name:String,grades:Number})
var stuModel = mongoose.model('grades',schema)
//保存查询数据的_id
var aIDArr = []
//查询所有数据
stuModel.find((err,docs) => {
if(!err){
docs.forEach((item,index,arr)=>{
aIDArr.push(item._id)
})
//显示第 0 个元素的所有字段
stuModel.findById(aIDArr[0],(err,doc)=>{
if(!err){
console.log(doc)
}
})
// { _id: 6017befb5c36d64d08b72576, name: '小明', grades: 68, __v: 0 }
//显示第 0 个元素且只输出name字段
stuModel.findById(aIDArr[0],{name:1,_id:0},(err,doc)=>{
if(!err){
console.log(doc)
}
})
// { name: '小明' }
//显示第 0 个元素且输出最少的字段(_id默认输出)
stuModel.findById(aIDArr[0],{lean:true},(err,doc)=>{
if(!err){
console.log(doc)
}
})
// { _id: 6017befb5c36d64d08b72576 }
}
})
}
})
注:conditions写一个id值就可以了,返回单个文档
【findOne()】
-
返回查询到的数据的第一个
// 返回查询到的数据的第一个
BookModel.findOne({price:{$gt:10}},(err,doc) => {
if(!err){
console.log(doc)
}
})
复杂查询【$where】
-
$where 可以使用任意的 JavaScript 作为查询的一部分,包含JavaScript 表达式的字符串或者函数
// 字符串 es5中this与obj指向一样,es6中只能用obj
BookModel.find({$where:"this.name == this.author" || "obj.name == obj.author"},(err,doc) => {
if(!err){
console.log(doc)
}
})
//函数
BookModel.find({$where:function() {
return this.name == this.author || obj.name == obj.author
}},(err,doc) => {
if(!err){
console.log(doc)
}
})
常用查询条件
stuModel.find({grades:{$gt:90}},(err,docs)=>{
console.log(docs);
})
特定类型查询
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student')
var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})
var stuModel = mongoose.model('grades', Schema);// 按test从小到大排序
stuModel.find().sort('test').exec((err,docs)=>{
console.log(docs)
})
// 按test从大到小排列
stuModel.find().sort('-test').exec((err,docs)=>{
console.log(docs)
})
// 跳过1个,显示其他
stuModel.find().skip(1).exec((err,docs)=>{
console.log(docs)
})
// 显示2个
stuModel.find().limit(2).exec((err,docs)=>{
console.log(docs)
})
// 显示name、grades字段,不显示_id字段
stuModel.find().select('name grades -_id').exec((err,docs)=>{
console.log(docs)
})
// 跳过第1个后,只显示2个数据,按照grades由大到小排序,且不显示_id字段
stuModel.find().skip(1).limit(2).sort('-grades').select('-_id').exec((err,docs)=>{
console.log(docs)
/*[{ name: '小明', grades: 78, __v: 0, test: 1 },
{ name: '小花', grades: 76, test: 4, __v: 0 }]*/
})
// 显示集合stuModel中的文档数量
stuModel.find().count((err,count)=>{
console.log(count)
//6
})
// 返回集合stuModel中的grades的值
stuModel.find().distinct('grades',(err,distinct)=>{
console.log(distinct)
//[ 46, 52, 60, 76, 78, 94 ]
})
文档更新
【update()】
-
Model.update(conditions, doc, [options], [callback])
-
参数
conditions:查询条件
doc:需要修改的数据(插入的数据)
[options]:控制选项
safe (boolean): 默认为true。安全模式。
upsert (boolean): 默认为false。如果不存在则创建新记录。
multi (boolean): 默认为false。是否更新多个查询记录。
runValidators: 如果值为true,执行Validation验证。
setDefaultsOnInsert: 如果upsert选项为true,在新建时插入文档定义的默认值。
strict (boolean): 以strict模式进行更新。
overwrite (boolean): 默认为false。禁用update-only模式,允许覆盖记录。
-
[callback]:回调函数
-
若设置了查询条件,当数据库不满足时默认什么也不发生
-
update() 方法中的回调函数不能省略,否则数据不会更新,当回调无有用信息时可以使用exec()简化
stuModel.update({grades:{$gt:80}},{test:40},function(err,raw){
//{ n: 1, nModified: 1, ok: 1 }
console.log(raw);
})
如果要同时更新多个记录,需要设置options里的multi为true。
temp.update({name:/a/},{age: 10},{multi:true},function(err,raw){
//{ n: 2, nModified: 2, ok: 1 }
console.log(raw);
})
【updateOne()】
-
Model.updateOne(conditions, doc, [options], [callback])
-
与update()相似,唯一区别为updateOne() 默认更新一个文档,即使设置{multi:true}也无法只更新一个文档
【updateMany()】
-
Model.updateMany(conditions, doc, [options], [callback])
-
与update()相似,唯一区别为updateMany() 默认更新多个文档,即使设置{multi:false}也无法只更新一个文档
【find()+save()】 【findOne() + save()】
用于复杂更新
const mongoose = require('mongoose')
mongoose.connect('mongodb://localhost:27017/student',err=>{
if(!err){
var Schema =new mongoose.Schema({ name:String,grades:Number,test:{type:Number,default:0}})
var stuModel = mongoose.model('grades',Schema)
//查询成绩小于60的数据,并在其名字后添加‘:差生’字段
stuModel.find({grades:{$lt:60}},(err,docs)=>{
console.log(docs);
/*[{test: 0,_id: 6017c455ba09d355a49ec8eb,name: '小红',grades: 52,__v: 0},
{test: 0,_id: 6017c455ba09d355a49ec8ec,name: '小刚',grades: 46,__v: 0}]*/
docs.forEach((item,index,arr) => {
item.name += ':差生'
//将修改后的数据保存
item.save()
})
console.log(docs)
/*[{test: 0,_id: 6017c455ba09d355a49ec8eb,name: '小红:差生',grades: 52,__v: 0},
{test: 0,_id: 6017c455ba09d355a49ec8ec,name: '小刚:差生',grades: 46,__v: 0}]*/
})
}
})
文档删除
【remove()】
-
会删除符合条件的所有数据
// 数据删除
BookModel.remove({name:/西游记/},function(err){})
【findOneAndRemove()】
-
删除符合条件的一条数据
-
Model.findOneAndRemove(conditions, [options], [callback])
-
回调不可省略,但可以使用exec() 简写
stuModel.findOneAndRemove({name:/差生/}).exec()
【findByIdAndRemove()】
-
通过id删除数据(id是唯一的)
-
Model.findByIdAndRemove(conditions, [options], [callback])
-
回调不可省略,但可以使用exec() 简写
开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!
更多推荐
所有评论(0)