Mongoose
简介
Mongoose 是一个ODM(对象文档映射库—Object-Document Mapping Library)。
Mongoose 为模型提供了一种直接的,基于 scheme 结构去定义你的数据模型,然后通过实例化模型来生成一条数据文档;而在数据模型上可以使用各种内置的方法。
例如:
db.collection("users").insertOne({ name: "Jon", age: 28, password: "hsdjkffds", });——>
const user = User.create({ name: "Jon", age: 28, password: "hsdjkffds" });
安装
npm install --save mongoose
基础使用
连接数据库
app.js
const mongoose = require('mongoose'); // 引入mongoose
...
mongoose
.connect(
'mongodb+srv://<user>:<password>@cluster0.mnle1m2.mongodb.net/shop?retryWrites=true&w=majority'
) // 连接MongoDB数据库
.then(result => {
app.listen(3000);
})
.catch(err => {
console.log(err);
});
创建和定义模型的 Schema
以键值对的方式来定义模型:
models/product.js
const mongoose = require("mongoose");
const Schema = mongoose.Schema;
const productSchema = new Schema({
// @1
title: {
type: String, // 类型
required: true, // 是否必须
},
price: {
type: Number,
required: true,
},
description: {
type: String,
required: true,
},
imageUrl: {
type: String,
required: true,
},
});
module.exports = mongoose.model("Product", productSchema); // 将导出的模块作为mongoose的model,方便日后连接 @2
@1:虽然 MongoDB 是没有特定的 schema 限制的,但通常我们在使用时知道某种数据存在某种结构(比如知道 name 数据用 String 类型);因此 mongoose 需要我们提供这样的结构,让我们只关注于数据本身,即使这样做会放弃一些数据的灵活性。
@2:第一个参数为自定义的集合名字(Mongoose 会将这个名字的开头转为小写,并在后面加上 s 作为集合的名字),第二个参数为需要导出的模块。
自定义 Schema 的方法
我们可以向定义的 Schema 中添加方法,让每个通过这个 Schema 模型创建出来的实例(数据/文档)都可以使用。
const productSchema = new Schema({
...
});
productSchema.methods.addToCart = function(product) {
...
} // 向productSchema中添加addToCart方法
向集合中新增一条数据(文档)
集合名字在导出时通过mongoose.model已经定义好了,当我们通过创建模型的实例时会添加到对应的集合中,然后通过save()来保存一条数据:
controllers/admin.js
const Product = require("../models/product");
exports.postAddProduct = (req, res, next) => {
const title = req.body.title;
const imageUrl = req.body.imageUrl;
const price = req.body.price;
const description = req.body.description;
const product = new Product({
// 创建模型实例并写入数据
title: title,
price: price,
description: description,
imageUrl: imageUrl,
});
product
.save() // 保存一条数据
.then((result) => {
console.log("Created Product");
res.redirect("/admin/products");
})
.catch((err) => {
console.log(err);
});
};
查询数据
查询所有数据
使用find()查询所有的数据:
const Product = require("../models/product");
exports.getProducts = (req, res, next) => {
Product.find() // 查询所有数据
.then((products) => {
res.render("shop/product-list", {
prods: products,
pageTitle: "All Products",
path: "/products",
});
})
.catch((err) => console.log(err));
};
查询条件数据
**findById()**——根据 id 查询数据
exports.getProduct = (req, res, next) => { const prodId = req.params.productId; Product.findById(prodId) // 根据id(_id)查询数据 .then((product) => { res.render("shop/product-detail", { product: product, pageTitle: product.title, path: "/products", }); }) .catch((err) => console.log(err)); };
更新数据
更新数据只需要找到对应数据修改后,再使用save()。
exports.postEditProduct = (req, res, next) => {
const prodId = req.body.productId;
const updatedTitle = req.body.title;
const updatedPrice = req.body.price;
const updatedImageUrl = req.body.imageUrl;
const updatedDesc = req.body.description;
Product.findById(prodId) // 根据id找到对应数据
.then((product) => {
// 对数据进行修改
product.title = updatedTitle;
product.price = updatedPrice;
product.description = updatedDesc;
product.imageUrl = updatedImageUrl;
return product.save(); // 保存新修改的数据
})
.then((result) => {
console.log("UPDATED PRODUCT!");
res.redirect("/admin/products");
})
.catch((err) => console.log(err));
};
删除数据
根据 id 删除数据
可以使用 Mongoose 内置的findByIdAndRemove来删除对应数据。
exports.postDeleteProduct = (req, res, next) => {
const prodId = req.body.productId;
Product.findByIdAndRemove(prodId) // 删除数据
.then(() => {
console.log("DESTROYED PRODUCT");
res.redirect("/admin/products");
})
.catch((err) => console.log(err));
};
嵌入式文档
在 MongoDB 中,集合和集合之间一般是没有关联的,但可以使用嵌入式文档,将复制的关联 id 产生联系。
创建关系
如果想让一个集合和另一个集合有关系,可以使用ref来嵌入关系。
models/product.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const productSchema = new Schema({
...
userId: {
type: Schema.Types.ObjectId,
ref: 'User', // 设置关联
required: true
}
});
module.exports = mongoose.model('Product', productSchema);
models/admin.js
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
const userSchema = new Schema({
...
cart: {
items: [
{
productId: { type: Schema.Types.ObjectId, ref: 'Product', required: true }, // 设置关联
quantity: { type: Number, required: true }
}
]
}
});
module.exports = mongoose.model('User', userSchema);
附录
const Product = require('..');
const product = new Product({...});
save()
向集合中保存/新增一条数据。
product.save();
find()
查询所有数据。返回一个 Promise。
Product.find();
findOne()
查询所有数据但只返回一条数据(文档)。返回一个 Promise。
Product.findOne();
findById()
根据 id(_id)查询数据。返回一个 Promise。
Product.findById(prodId);
findByIdAndRemove()
根据 id(_id)删除数据。
Product.findByIdAndRemove(prodId);
deleteOne()
根据指定信息删除一条数据。
Product.deleteOne({ _id: prodId, userId: req.user._id });
populate()
填充字段,将文档中的指定路径自动替换为来自其他集合的文档的过程。返回一个 Promise。
Product.find().populate();
select()
筛选字段,将数据中与之匹配的筛选出来。
Product.find().select();
以字符串空格的方式筛选不同字段:
Product.find().select("title price _id");