基于 Mongoose
的 Node.js
MongoDB
数据库关系模型绑定
项目使用 MongoDB
非关系型数据库进行存储,保存为 BSON
格式,称一个记录为文档(Document)
使用 mongoose
进行文档与 JavaScript
对象的对应。
这种对应分三步:
导入 mongoose
假设我们要实现 UserModel
(已经实现了),那么在 src/model
下建立 userModel.ts
文件,引入 mongoose
import {ObjectId} from "mongodb";
import {model, Schema} from "mongoose";
建立 Interface
Interface
是对象在程序内的表示。
interface User {
"_id"?: ObjectId,
"nickName": string,
"avatar"?: string,
"gender"?: number,
"phoneNumber": string,
"playedScripts"?: Array<ObjectId>,
"likedScripts"?: Array<ObjectId>,
"coins": number
}
这部分使用的是 TypeScript
的 interface
语法,其规则与 Java
的 Interface
十分相似。
建立 Schema
Schema
是对象在数据库内的表示,将程序内的对象对应到数据库里。
const userSchema = new Schema<User>({
"nickName": String,
"avatar": {type: String, default: ""},
"gender": {type: Number, default: 0}, // 0:未知,1:男性,2:女性
"phoneNumber": String,
"playedScripts": Array,
"likedScripts": Array,
"coins": Number
})
注意 Schema
中 String
等类型首字母要大写,interface
里全部小写
建立 Model
export const userModel = model<User>("user", userSchema)
// User: 刚刚建立的 Interface
// "user": 对应的数据库的集合的名字
// userSchema: 刚刚定义的 Schema
// userModel: 导出的用户模型
Model
的使用
mongoose
的 Model
基本继承了 MongoDB
的所有操作,如 findOne
、insertOne
、deleteOne
、updateOne
、aggregate
等。
增加
在需要 userModel
的文件里
import {userModel} from "../model/userModel";
export const serverLoginExecutor: Executor = async (payload: IRequestServerLogin) => {
// ...
const newUser = new userModel({
nickName: "default",
phoneNumber: payload.phoneNumber
})
await newUser.save()
// ...
}
通过 new
来建立一个 userModel
的实例,执行 save
方法(注意这个方法是异步的,需要 await
)
const newProduct = await product.save();
newProduct === product; // true
删除
await userModel.deleteOne({ name: 'Eddard Stark' }); // returns {deletedCount: 1}
查找
findById
https://mongoosejs.com/docs/api.html#model_Model.findById
// Find the adventure with the given `id`, or `null` if not found
await Adventure.findById(id).exec();
// using callback
Adventure.findById(id, function (err, adventure) {});
// select only the adventures name and length
await Adventure.findById(id, 'name length').exec();
findOne
https://mongoosejs.com/docs/api.html#model_Model.findOne
// Find one adventure whose `country` is 'Croatia', otherwise `null`
await Adventure.findOne({ country: 'Croatia' }).exec();
// using callback
Adventure.findOne({ country: 'Croatia' }, function (err, adventure) {});
// select only the adventures name and length
await Adventure.findOne({ country: 'Croatia' }, 'name length').exec();
find
https://mongoosejs.com/docs/api.html#model_Model.find
// find all documents
await MyModel.find({});
// find all documents named john and at least 18
await MyModel.find({ name: 'john', age: { $gte: 18 } }).exec();
// executes, passing results to callback
MyModel.find({ name: 'john', age: { $gte: 18 }}, function (err, docs) {});
// executes, name LIKE john and only selecting the "name" and "friends" fields
await MyModel.find({ name: /john/i }, 'name friends').exec();
// passing options
await MyModel.find({ name: /john/i }, null, { skip: 10 }).exec();
更新
https://mongoosejs.com/docs/api.html#query_Query-updateOne
const res = await Person.updateOne({ name: 'Jean-Luc Picard' }, { ship: 'USS Enterprise' });
res.n; // Number of documents matched
res.nModified; // Number of documents modified
https://mongoosejs.com/docs/api.html#model_Model.updateMany
const res = await Person.updateMany({ name: /Stark$/ }, { isDeleted: true });
res.matchedCount; // Number of documents matched
res.modifiedCount; // Number of documents modified
res.acknowledged; // Boolean indicating everything went smoothly.
res.upsertedId; // null or an id containing a document that had to be upserted.
res.upsertedCount; // Number indicating how many documents had to be upserted. Will either be 0 or 1.
聚合函数
实现对数据的流水线操作
const aggregate = Model.aggregate([
{ $project: { a: 1, b: 1 } },
{ $skip: 5 }
]);
Model.
aggregate([{ $match: { age: { $gte: 21 }}}]).
unwind('tags').
exec(callback);
可以参考:https://www.runoob.com/mongodb/mongodb-aggregate.html