模型
模型 是從 Schema
定義編譯而來的精巧建構函式。模型的一個實例稱為文件。模型負責從底層 MongoDB 資料庫建立和讀取文件。
編譯您的第一個模型
當您對 schema 呼叫 mongoose.model()
時,Mongoose 會為您編譯一個模型。
const schema = new mongoose.Schema({ name: String, size: String });
const Tank = mongoose.model('Tank', schema);
第一個參數是您的模型所針對的集合的單數名稱。Mongoose 會自動查找模型名稱的複數、小寫版本。 因此,對於上面的範例,模型 Tank 是針對資料庫中的 tanks 集合。
注意: .model()
函式會複製 schema
。請確保在呼叫 .model()
之前,您已將所有想加入 schema
的內容,包括 hook 都加入!
建構文件
模型的一個實例稱為文件。建立它們並儲存到資料庫很容易。
const Tank = mongoose.model('Tank', yourSchema);
const small = new Tank({ size: 'small' });
await small.save();
// or
await Tank.create({ size: 'small' });
// or, for inserting large batches of documents
await Tank.insertMany([{ size: 'small' }]);
請注意,在您的模型使用的連線開啟之前,不會建立/移除任何 tank。每個模型都有一個相關聯的連線。當您使用 mongoose.model()
時,您的模型將使用預設的 mongoose 連線。
await mongoose.connect('mongodb://127.0.0.1/gettingstarted');
如果您建立自訂連線,請改用該連線的 model()
函式。
const connection = mongoose.createConnection('mongodb://127.0.0.1:27017/test');
const Tank = connection.model('Tank', yourSchema);
查詢
使用 Mongoose 查找文件很容易,它支援 MongoDB 的豐富查詢語法。可以使用 model
的find、findById、findOne 或 where 靜態函式來檢索文件。
await Tank.find({ size: 'small' }).where('createdDate').gt(oneYearAgo).exec();
有關如何使用 Query API 的更多詳細資訊,請參閱查詢章節。
刪除
模型具有靜態的 deleteOne()
和 deleteMany()
函式,用於移除所有符合給定 filter
的文件。
await Tank.deleteOne({ size: 'large' });
更新
每個 model
都有自己的 update
方法,用於修改資料庫中的文件,而無需將它們返回到您的應用程式。有關更多詳細資訊,請參閱 API 文件。
// Updated at most one doc, `res.nModified` contains the number
// of docs that MongoDB updated
await Tank.updateOne({ size: 'large' }, { name: 'T-90' });
如果您想更新資料庫中的單個文件並將其返回到您的應用程式,請改用 findOneAndUpdate。
變更串流
變更串流為您提供了一種監聽所有通過 MongoDB 資料庫的插入和更新的方法。請注意,除非您連線到 MongoDB 副本集,否則變更串流無法運作。
async function run() {
// Create a new mongoose model
const personSchema = new mongoose.Schema({
name: String
});
const Person = mongoose.model('Person', personSchema);
// Create a change stream. The 'change' event gets emitted when there's a
// change in the database
Person.watch().
on('change', data => console.log(new Date(), data));
// Insert a doc, will trigger the change stream handler above
console.log(new Date(), 'Inserting doc');
await Person.create({ name: 'Axl Rose' });
}
上面 async 函式的輸出將如下所示。
2018-05-11T15:05:35.467Z '正在插入文件' 2018-05-11T15:05:35.487Z '已插入文件' 2018-05-11T15:05:35.491Z { _id: { _data: ... }, operationType: 'insert', fullDocument: { _id: 5af5b13fe526027666c6bf83, name: 'Axl Rose', __v: 0 }, ns: { db: 'test', coll: 'Person' }, documentKey: { _id: 5af5b13fe526027666c6bf83 } }您可以在這篇部落格文章中閱讀有關 mongoose 中變更串流的更多資訊。
視圖
MongoDB 視圖本質上是唯讀集合,其中包含使用聚合從其他集合計算出的資料。在 Mongoose 中,您應該為每個視圖定義單獨的模型。您也可以使用createCollection()
建立視圖。
以下範例顯示如何基於 User
模型建立新的 RedactedUser
視圖,該視圖會隱藏潛在的敏感資訊,例如姓名和電子郵件。
// Make sure to disable `autoCreate` and `autoIndex` for Views,
// because you want to create the collection manually.
const userSchema = new Schema({
name: String,
email: String,
roles: [String]
}, { autoCreate: false, autoIndex: false });
const User = mongoose.model('User', userSchema);
const RedactedUser = mongoose.model('RedactedUser', userSchema);
// First, create the User model's underlying collection...
await User.createCollection();
// Then create the `RedactedUser` model's underlying collection
// as a View.
await RedactedUser.createCollection({
viewOn: 'users', // Set `viewOn` to the collection name, **not** model name.
pipeline: [
{
$set: {
name: { $concat: [{ $substr: ['$name', 0, 3] }, '...'] },
email: { $concat: [{ $substr: ['$email', 0, 3] }, '...'] }
}
}
]
});
await User.create([
{ name: 'John Smith', email: 'john.smith@gmail.com', roles: ['user'] },
{ name: 'Bill James', email: 'bill@acme.co', roles: ['user', 'admin'] }
]);
// [{ _id: ..., name: 'Bil...', email: 'bil...', roles: ['user', 'admin'] }]
console.log(await RedactedUser.find({ roles: 'admin' }));
請注意,Mongoose 目前不強制執行視圖為唯讀。如果您嘗試從視圖 save()
文件,您將收到來自 MongoDB 伺服器的錯誤。
還有更多
API 文件涵蓋了許多其他可用的方法,例如 count、mapReduce、aggregate 等等。
下一步
現在我們已經介紹了 Models
,讓我們看一下文件。