MongoDB和Mongoose的入门教学

孔阳炎
2023-12-01

        MongoDB现在绝对是市面上最受欢迎的noSql数据库,本文将简单讲解Mongoose和MongoDB的语法和特点。

目录

什么是MongoDB和Mongoose?

在Node中链接MongoDB数据库

定义Mongoose的对象模式schema

MongoDB的增删改查

        查找和创建操作     

        更新操作

        删除操作​​​​​​​


什么是MongoDB和Mongoose?

        MongoDB是一个关系模型数据库,他们最大的好处是可以继续使用JSON对象而不需要转换成数据库语义的思维。MongoDB自身并没有对象模式schema模型model,所以对于新手而言,开发者也拥有了更多的控制和操作空间。但更多的操作空间也意味着更多的犯错的机会。

        Mongoose是MongoDB的对象建模工具,他可以帮我们创建schema和model以减少错误发生的机会。

        

在Node中链接MongoDB数据库

        首先,请使用这个链接,并且根据指示下载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
})

定义Mongoose的对象模式schema

        首先,我们通常会新建一个文件夹,来装载我们所有的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里的数据,我们不仅可以定义数据类型,还可以添加额外的选项。其中包括:

  • 默认值:default
  • 内置校验器:比如min:5和max:10
  • 是否必填:required:true
  • 是否将string转换成大小写,去除两端空格:lowercase: true,trim: true​​​​​​​


        那么接下来,让我们真正创建一个用户的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就会对相关集合产生作用。


MongoDB的增删改查

        查找和创建操作     

        现在,我们可以按照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的入门教学。希望你在阅读过后,就已经可以进行简单的数据库操作了

 类似资料: