MongoDB现在绝对是市面上最受欢迎的noSql数据库,本文将简单讲解Mongoose和MongoDB的语法和特点。
目录
删除操作
MongoDB是一个关系模型数据库,他们最大的好处是可以继续使用JSON对象而不需要转换成数据库语义的思维。MongoDB自身并没有对象模式schema和模型model,所以对于新手而言,开发者也拥有了更多的控制和操作空间。但更多的操作空间也意味着更多的犯错的机会。
Mongoose是MongoDB的对象建模工具,他可以帮我们创建schema和model以减少错误发生的机会。
首先,请使用这个链接,并且根据指示下载MongoDB:https://www.mongodb.com/try/download/community
下载完成后,你还可以使用
其次,我们使用npm下载mongoose
npm install mongoose
在node文件中引入模块, 在你下载MongoDB后,登录MongoDB atlas网站,按照指示找到你的数据库网址。把网址中的<username>和<password>换成你的用户名和密码。
// 导入 mongoose 模块
const mongoose = require('mongoose');
// 你的mongodb的地址
const DB_URL = 'mongodb+srv://<username>:<password>@sandbox.o72ts.mongodb.net/?retryWrites=true&w=majority';
接下来,我们使用我们的数据库的链接于数据库链接。以下的这些设置会让你的程序使用新的url解析器,从而可以避免你使用被弃用的方法。
// 链接到数据库
mongoose.connect(DB_URL, {
useNewUrlParser: true,
useUnifiedTopology: true,
useCreateIndex: true,
useFindAndModify: false
})
首先,我们通常会新建一个文件夹,来装载我们所有的schema。但在我们真正开始创建我们的schema之前,先看一下常见的mongoose的schema可以声明的数据类型
const schema = new Schema(
{
name: String, 字符串
binary: Buffer, 2进制buffer
living: Boolean, 布尔值
date: Date, 日期
用对象声明配置,type指数据类型,default默认值
updated: { type: Date, default: Date.now },
数字类型的变量可以设置最大和最小值,required表示是否必填,接受布尔值
age: { type: Number, min: 18, max: 65, required: true },
mixed表示任意类型都可以
mixed: Schema.Types.Mixed,
数据库生成的唯一ID特定实例
_someId: Schema.Types.ObjectId,
array: [],数组
ofString: [String], // 定义数组内的值的类型
嵌套声明
nested: { stuff: { type: String, lowercase: true, trim: true } }
})
这里面你唯一可能不是很熟悉的就是ObjectId。ObjectId是你在数据库中插入数据时,数据库为该数据自动生成的独有的ID。我们通常使用这个独有值来对特定数据进行操作。该ID是一个class类。也就是说它其实是一个对象,但当你对ObjectID使用toSrting()方法时,你可以将它转换成一个24位字符串。
从上面你可能已经发现,如果我们使用对象定义schema里的数据,我们不仅可以定义数据类型,还可以添加额外的选项。其中包括:
那么接下来,让我们真正创建一个用户的schema
const mongoose = require('mongoose')
const userSchema = new mongoose.Schema({
name: String,
age: Number,
email: String,
createdAt: Date,
updateAt: Date,
bestFriend: mongoose.SchemaTypes.ObjectId,
hobbies: [String]
})
// 使用mongoose.model将schema定义给相关的集合
module.exports = mongoose.model('User', userSchema)
在我们定义完schema以后,我们首先需要使用mongoose.model()把该schema定义给相关的数据库中的集合collection。model()接受两个参数,第一个是集合名,第二个是schema值。使用后,我们定义的schema就会对相关集合产生作用。
现在,我们可以按照schema的格式,创造一些符合格式的用户数据出来。
按照一个实际的Express的写法,注册一个用户通常是使用post请求,然后我们可以获得请求体中的数据来作为用户的信息。
// 由于数据库操作的异步的,我们需要使用异步async函数
router.post('/register', async (req, res) => {
//用ES6对象解构的方式获得请求体数据
const { name, email, password, age, hobbies } = req.body
})
然后,我们需要知道数据库中是否已经存在此用户,如果存在的话,我们需要告知用户,该邮箱已经被使用。这时我们就需要使用查询方法。MongoDB中的查询方法最常用find(),findOne(),和findById()。 find会返回所有符合条件的数据,但是findOne和findById只会找到第一个符合条件的数据。他们第一个参数都接受一个条件对象,第二个参数projection表明回传的数据的字段,相当于sql的select。第三个参数是选项,我们暂时不需要。
因为我们不希望一个邮箱重复注册账户,所以我们使用该邮箱来进行数据库查找,如果该用户不存在,我们就往数据库中添加一个新的用户,使用create()或者save().
router.post('/', async (req, res) => {
const { name, email, password, age, hobbies } = req.body
const signupAuth = await User.findOne({ email: email })
// 使用try catch来进行错误处理
try {
if (signupAuth === null) {
let result = await User.create({ name, email, password, age, hobbies })
res.status(200).json(result)
} else {
res.json({ msg: 'this email is already used' })
}
} catch(err) {
console.log(err)
}
})
当我们需要更新一个用户的信息时,比如他的用户名或者密码,我们就需要使用到mongoDB的更新方式。MongoDB的更新方式不止一种,就像其他的操作一样,比如除了save()以外,我们还可以使用findOneAndUpdate(),两者的语法分别如下。
// 使用save方法,参数内必须有id值,不然将会被当做创建处理 COLLECTION_NAME.save({_id:ObjectId(),NEW_DATA})
// update的第一个参数是查找条件,第二个参数为更改内容 const res = await CompletedSchema.updateOne(<condition>, <query>)
例如,我们想要更新相关用户的用户名,我们要像之前一样,首先找到该用户,再将更新的信息提交到数据库中。
router.patch('/updateuser', async (req, res) => {
const { username, email } = req.body
const user = await User.findOne({ email: email })
try {
// 如果你使用的是express的auth中间件,我们会在用户登录时,将其id存储在request的auth值中使用
// 该值存储的属性名会根据中间件不同有差异
// new: true配置会在数据更新后将其返回
await User.findByIdAndUpdate(req.auth._id, updatedUser, { new: true })
} catch(err) {
res.json({ msg: 'error occured' })
}
})
删除操作的逻辑很简单,和更新没有什么本质区别,但他只有一个参数,同样也是用于确认条件来查找需要被删除的数据。常见方式为 deleteOne() 和 deleteMany()。
const res = await CompletedSchema.deleteOne(<condition>)
deleteMany()会删除所有符合条件的数据,大部分情况下,尽量是有deleteOne()以防误删。
数据库操作是可以十分复杂的,本文只作为一个MongoDB和mongoose的入门教学。希望你在阅读过后,就已经可以进行简单的数据库操作了