使用 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)
})