黑白梦

使用 Mongoose 操作 Mongodb

使用 Mongoose 操作 MongoDB ,建立模型,实现基础增删改查。

这是 freeCodeCamp 课程 “后端开发和 APIs” 中的 “MongoDB 和 Mongoose” 章节的学习和实践笔记。

MongoDB Atlas 创建数据库

在 MongoDB Atlas上设置托管数据库

https://www.freecodecamp.org/news/get-started-with-mongodb-atlas/

控制台 https://cloud.mongodb.com/v2/

在 DEPLOYMENT - Database 中可看到创建的集群,点击 Connect 查看 URI 。连接的 URI 需要补上数据库名称,如 /fcc-mongodb-and-mongoose

本地 DataGrip 连接:将 URL 设置成 mongodb+srv:// 开头,不带端口号。使用账户和密码即可登录。

Connect 链接数据库

安装:

npm install mongoose –-save

连接

require('dotenv').config(); // 读取 .env 文件
const mongoose = require('mongoose')

mongoose.connect(process.env.MONGO_URI, { useNewUrlParser: true, useUnifiedTopology: true });

MONGO_URI 配置如:

# 连接 mongo 并且使用 hbm 这个数据库,没有会自动新建
MONGO_URI="mongodb://localhost:27017/hbm"

如果是 MongoDB Atlas 等线上服务的 URI,按服务商的填入即可。

定义文档模型

定义文档模型,定义 Schema ,根据 Schema 创建模型。

// 定义 Schema
const personSchema = new mongoose.Schema({
  name: {
    type: String,
    required: true
  },
  age: Number,
  favoriteFoods: [String],
});
// 根据 Schema 创建模型
let Person = mongoose.model('Person', personSchema);

创建保存单个实例

通过 new 创建实例对象,通过 save 即可保存。笔记中忽略了异常处理,真实业务应处理异常。

const person = new Person({name: "hbm", age: 6, favoriteFoods: ["fries", "fried chicken", "cola"]});

person.save(function(err, data) {
  done(null, data)
});

批量新增 create

const arrayOfPeople = [
  {name: "hbm1", age: 16, favoriteFoods: ["fries", "fried chicken", "cola"]},
  {name: "hbm2", age: 26, favoriteFoods: ["fries", "fried chicken", "cola"]}
]
Person.create(arrayOfPeople, function(err, data) {
  done(null, data)
})

按条件查找数据

通过 find 寻找多条

Person.find({
  name: personName
}, function(err, data) {
  done(null, data)
})

通过 User.findOne找一条

Person.findOne({
  favoriteFoods: food
}, function(err, data) {
  done(null, data)
})

通过 findById 根据内部自动生成的 id 来找

Person.findById(personId, function(err, data) {
  done(null, data)
})

查询条件链式调用、分页查询

find 后不写回调函数就不会执行,可链式调研去加入筛选条件:

Person.find({
  favoriteFoods: foodToSearch
})
  .sort({ name: 1 })
  .limit(2)
  .select({ name: true, favoriteFoods:true })
  .exec(function(err, data) {
    done(null, data)
  })

Primise 调用

也支持通过 Primise then 调用,不需要写回调函数,点 then 或 await 就跟传了回调函数一样,就会走执行逻辑。

如这个分页逻辑:

Person.find()               // find all users
  .skip(100)                   // skip the first 100 items
  .limit(10)                   // limit to 10 items
  .sort({ name: 1 })      // sort ascending by firstName
  .exec()                      // execute the query
  .then((docs) => {
    console.log(docs);
  })
  .catch((err) => {
    console.error(err);
  });

更新实例保存

获取示例后,操作该对象,调用 save 保存。

Person.findById(personId, function(err, data) {
  data.favoriteFoods.push(foodToAdd)
  data.save(function(err, data) {
    done(null, data)
  })
})

查找一个并更新

findOneAndUpdate

Person.findOneAndUpdate(
  { name: personName},
  { age: ageToSet},
  { new: true }, // 返回修改后的对象
  function(err, data) {
    done(null, data)
  }
)

删除数据

findByIdAndRemove

Person.findByIdAndRemove(personId, function(err, data) {
  done(null, data)
})

findOneAndRemove

Person.findOneAndRemove({
  name: nameToRemove
}, function(err, data) {
  done(null, data)
})

remove

Person.remove({
  name: nameToRemove
}, function(err, data) {
  done(null, data)
})

更多内容