Nodejs-mongoose操作MongoDB

本文详细介绍了如何使用 Node.js 中的 Mongoose 模块操作 MongoDB 数据库,包括连接数据库、创建集合、插入数据、查询、删除、更新及验证等操作,并提到了关联集合的概念。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Nodejs 操作 MongoDB
连接 MongoDB 数据库

mongoose.connect(uri[, option][, callback]):该方法用于与 MongoDB 数据库建立连接

  • mongoose 导入的 mongoose 模块

参数

  • rui 连接 MongoDB 数据库的地址
  • options 该参数是一个对象,用于设置一些选项,这些选项会被传到底层 MongoDB 驱动
  • callback
创建集合

mongoose 的一切都始于 Schema, 通过 mongoose 导出的 Schema 构造函数可以创建集合,设定集合的结构(规则);mongoose 中的集合就相当于关系型数据库中的表结构,可以设置集合中字段的类型,默认值、约束等。

Schema(definition[,options]):构造函数,通过该函数可以设计集合的结构,然后通过 new 创建实例对象;使用该构造函数时要通过 mongoose.Schema 获取,比如:new mongoose.Schema()

参数:

  • definition 该参数是一个对象,通过该参数定义集合中的字段并对字段设置相关约束
  • options
应用规则

mongoose.model(name[,schema]):将文档结构发布为模型(应用规则);返回值为模型构造函数。

参数

  • name 字符串,首字母大写的名词的单数形式,用来表示文档(模型)的名称; mongoose 会自动将该单词生成小写复数的集合名称
  • schema 该参数为设计的集合结构 (规则)
创建文档1

所谓的创建文档就是向集合中插入数据,该过程分为两步:创建集合实例,然后调用实例对象下的 save 方法将数据保存到数据库中

创建集合实例:

获取 model() 方法的返回的构造函数,该构造函数接收一个对象为参数,通过这个对象传入具体的数据,然后通过 new 关键字来创建实例对象

保存数据:

Model.prototype.save([options][,options.safe][,options.validateBeforeSave][,fn] ):该方法为 Model 原型上的方法,用于保存数据;有多个参数常用的为 fn

参数

  • fn 在数据保存完成后执行的回调函数,该函数有两个参数:错误对象 err,没有错误时值为 null;另一个参数为执行结果 doc(就是保存的数据)
创建文档2

Model.create(doc[,callback]) 将一个或多个文档保存到数据库的快捷方式;该方法的返回值为 promise 对象。

  • Model 调用 model() 方法后的返回值

参数

  • doc 需要插入集合中的文档,该参数可以是对象或数组
  • callback 数据插入完成后执行的回调函数;该函数有两个参数:错误参数对象 err 和保存的数据 doc

因为该方法的返回值为 promise 对象,所以可以省略回调函数,直接使用链式编程的方式。

下面举个例子:

// 引包
const mongoose = require('mongoose')

// 连接 MongoDB 数据库,数据库不存在时会自动创建
mongoose
  .connect('mongodb://localhost/userInfo', {
    useNewUrlParser: true,
    useUnifiedTopology: true
  })
  .then(() => console.log('数据库连接成功'))
  .catch(err => console.log('数据库连接失败', err))

// 设计集合结构(类似于表结构)
const userSchema = new mongoose.Schema({
  username: {
    type: String, // 设置字段类型
    required: true // 约束不能为空
  },
  age: Number,
  gender: Boolean,
  hobby: Array
})

// 应用集合
let User = mongoose.model('User', userSchema)

/* 创建文档1 */
// 拿到模型构造函数,开始为所欲为(插入数据)
let admin = new User({
  username: 'admin',
  age: 19,
  gender: false,
  hobby: ['book', 'music', 'shopping']
})

// 数据持久化(保存数据)
admin.save((err, res) => {
  if (err) console.log('保存失败!', err)
  else console.log('保存成功!', res)
})

/* 创建文档2 */
// 通过该方法不需要去实例化集合
User.create(
  {
    username: 'VIP',
    age: 18,
    gender: true,
    hobby: ['running', 'basketball', 'anime']
  },
  (err, doc) => {
    if (err) console.log('保存失败!', err)
    else console.log('保存成功', doc)
  }
)

/* 创建文档2 可写成如下形式*/
// User.create({
//   username: 'VIP',
//   age: 18,
//   gender: true,
//   hobby: ['running', 'basketball', 'anime']
// })
//   .then(doc => console.log('保存成功', doc))
//   .catch(err => console.log('保存失败!', err))

在这里插入图片描述

查询数据

Model.find(conditions[,callback]):用于查询集合中的文档(数据)
参数

  • conditions 查询条件,其值为一个对象,条件为多个时用逗号隔开;如果省略不写将获取集合中的所有文档
  • callback 查询完成后执行的回调函数,有两个参数
    • err 错误信息,成功时值为 null
    • docs 一个包含文档的数组,未查询到时为一个空数组

Model.findOne(conditions[,callback]):用于查询集合中符合条件的第一条文档(数据);参数同上,不同的是 callback 的 doc 为查询到的一条文档,未查询到时值为 null。

举个栗子:

// 引包
const mongoose = require('mongoose')

// 连接 MongoDB 数据库,数据库不存在时会自动创建
mongoose
  .connect('mongodb://localhost/userInfo', {
    useNewUrlParser: true,
    useUnifiedTopology: true
  })
  .then(() => console.log('数据库连接成功'))
  .catch(err => console.log('数据库连接失败', err))

// 设计集合结构(类似于表结构)
const userSchema = new mongoose.Schema({
  username: {
    type: String, // 设置字段类型
    required: true // 约束不能为空
  },
  age: Number,
  gender: Boolean,
  hobby: Array
})

// 应用集合
let User = mongoose.model('User', userSchema)

// 通过指定条件查询文档
User.find({ _id: '5dfc35f15057e028f49f4d39' }, (err, docs) => {
  if (err) console.log(err)
  else console.log(docs)
})

在这里插入图片描述

常见查询条件

$lt:小于;$gt:大于

// 获取 User 集合中 age 大于 16 小于 23 的文档
User.find({ age: {$gt: 16, $lt: 23} }).then(docs => console.log(docs))

$in:包含

// 获取 User 集合中 hobby 包含 'music' 的文档
User.find({ hobby: {$in: ['music']} }).then(docs => console.log(docs))

select(arg ):指定查询到的文档包含或排除哪些字段进行显示;需要注意的是包含和排除不能同时使用。

// 排除 username 和 age 字段,不进行显示
User.find()
  .select('-username -age')
  .then(docs => console.log(docs))
  • arg 该参数可以是一个字符串或对象;为字符串时多个字段之间用空格隔开,通过在字段前加 - 前缀可以进行排除

sort(arg):对查询到的文档进行排序

  • arg 一个字段,默认升序排列,降序排列时在字段前加一个 - 前缀即可
// 按照 age 升序排列
User.find()
  .sort('age')
  .then(docs => console.log(docs))

skip(val):跳过指定条数的文档

  • val 数量
// 跳过 2 条数据
User.find()
  .skip(2)
  .then(docs => console.log(docs))

limit(val):限制显示文档的最大条数

// 显示 10 条数据
User.find()
  .limit(10)
  .then(docs => console.log(docs))
删除数据

findOneAndDelete([conditions][,callback]):删除第一条匹配的文档;findOneAndRemove() 的功能与此方法相同

参数:

  • conditions 该参数是一个对象用于指定查询条件
  • callback 删除完成后执行的回调函数;有两个参数,错误信息 err 和 被删除的文档 doc
// 删除第一条 username 为 'VIP' 的文档
User.findOneAndDelete({ username: 'VIP' }, (err, doc) => {
  if (err) console.log(err)
  else console.log(doc)
})

deleteMany([filter][,callback]):删除符合条件的文档(多条);参数同上,不同的是回调函数的第二个参数为删除结果。

// 删除所有匹配的文档
User.deleteMany({ username: 'VIP' }, (err, docs) => {
  if (err) console.log(err)
  else console.log(docs)
})

在这里插入图片描述

更新数据

updateOne([criteria][,doc][,callback]):更新匹配到的第一条文档;fandOneAndUpdate() 的功能与此方法相同

参数:

  • criteria 查询条件
  • doc 需要更新的文档字段
  • callback 更新完成后执行的回调函数;有两个参数:
    • err 错误信息
    • writeOpResult 执行成功后的结果
// 更新匹配到的第一条文档的数据
User.updateOne({ username: 'www' }, { age: 666 }, (err, res) => {
  if (err) console.log(err)
  else console.log(res)
})

在这里插入图片描述
updateMany():更新匹配到的所有文档;参数同上。

// 更新匹配的所有文档
User.updateMany({ username: 'www' }, { age: 123 }, (err, res) => {
  if (err) console.log(err)
  else console.log(res)
})

在这里插入图片描述

mongoose 验证

required 设置是否为必传字段,其值为布尔值 true 表示必传;当值为数组时可追加错误时的提示信息

required: [ true, '该字段为必填字段']

unique 设置字段具有唯一性;其值为布尔值 true 表示不可重复

unique: true

minlength 设置当前字段的最小长度

minlength: [6, '该字段最小长度为 6']

maxlength 设置当前字段的最大长度

min 设置最小数值

max 设置最大数值

enum 枚举,设置当前字段可拥有的值值为数组

gender: {
    type: String,
    enum: ['男', '女', '妖精', '保密']
  }

trim 是否祛除字符串首尾的空格,为 true 时表示祛除

validate 自定义验证器;其值为一个对象,该对象的 validator 属性的属性值为一个函数,通过该函数可以自定义对字段的验证(函数的返回值为布尔值,为 true 时表示验证成功,否则验证失败)

intro: {
  type: String,
  // 自定义验证
  validate: {
    // val 为要验证的值
    validator: val => {
      return val && val >= 5
    },
    // 自定义验证信息
    message: '最少5个字符'
  }
}

default 设置默认值

举个例子:

// 引包
const mongoose = require('mongoose')

// 连接 MongoDB 数据库,数据库不存在时会自动创建
mongoose
  .connect('mongodb://localhost/userInfo', {
    useNewUrlParser: true,
    useUnifiedTopology: true
  })
  .then(() => console.log('数据库连接成功'))
  .catch(err => console.log('数据库连接失败', err))

// 设计集合结构(类似于表结构)
const userSchema = new mongoose.Schema({
  username: {
    // 设置字段类型
    type: String,
    // 约束不能为空
    required: [true, '用户名不能为空'],
    // 最小长度
    minlength: [6, '用户名最小长度为 6'],
    // 最大长度
    maxlenght: [12, '用户名最大长度为 12'],
    // 祛除首尾空格
    trim: true
  },
  age: {
    // 类型为 数字
    type: Number,
    // 最小值
    min: 16,
    // 最大值
    max: 23
  },
  regDate: {
    // 日期类型
    type: Date,
    // 默认值;Date.now 当前时间
    default: Date.now
  },
  gender: {
    type: String,
    // 枚举
    enum: ['男', '女', '妖精', '保密']
  },
  intro: {
    type: String,
    // 自定义验证
    validate: {
      // val 为要验证的值
      validator: val => {
        return val && val.length >= 5
      },
      // 自定义验证信息
      message: '最少5个字符'
    }
  }
})

// 应用集合
let User = mongoose.model('userInfo', userSchema)

User.create(
  {
    username: 'VIP',
    age: 20,
    gender: '',
    intro: '超级VIP会员!'
  },
  (err, doc) => {
    if (err) {
      // 获取错误对象
      let error = err.errors
      // 打印 message 信息
      for (let attr in error) {
        console.log(error[attr].message)
      }
    } else console.log('保存成功', doc)
  }
)

在这里插入图片描述

关联集合

集合之间默认是没有关联的,通常一些不同集合之间的数据之间有着某种关系,比如文章信息和文章作者的信息存储在不同集合中,但是文章是某个用户发表的,要查询文章的作者信息,就需要用到关联集合。

集合之间一般是使用 id 进行关联关联,然后通过 populate() 方法进行关联集合查询。

示例:

// 引入 mongoose 操作数据库
const mongoose = require('mongoose')
// 连接数据库
mongoose
  .connect('mongodb://localhost/userInfo', {
    useNewUrlParser: true,
    useUnifiedTopology: true
  })
  // 连接成功
  .then(() => console.log('数据库连接成功'))
  // 连接失败
  .catch(err => console.log(err, '数据库连接失败'))

// 设计用户集合结构
const userSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  }
})
// 设计文章集合结构
const postSchema = new mongoose.Schema({
  title: {
    type: String
  },
  author: {
    // 通过 id 与用户集合进行关联
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }
})
// 应用用户集合
const User = mongoose.model('User', userSchema)
// 应用文章集合
const Post = mongoose.model('Post', postSchema)

// 创建用户文档
User.create({ name: 'boy' }).then(result => console.log(result))
// 创建文章文档
Post.create({ titile: 'www', author: '5dfcb365bf9f50355c0e299a' }).then(
  result => console.log(result)
)
// 关联查询
Post.find()
  .populate('author')
  .then(result => console.log(result))
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值