Documents
mongoose 的 document 與MongoDB 的 document 一一對應。每個document都是它的model的實例。
1、檢索
在MongoDB中有很多方法檢索document。我們不會在這一節中涉及。詳細請看 querying 節。
2、更新
有很多種方法修改 document。我們首先看傳統方法findById。
Tank.findById(id, function (err, tank) { if (err) return handleError(err); tank.size = 'large'; tank.save(function (err) { if (err) return handleError(err); res.send(tank); }); });
這種方法包括先從Mongo檢索document,然后發出修改命令(通過調用保存觸發)。可是,如果我們不需要在應用程序中返回document而是只不過想直接修改數據庫中的屬性,Model#update 適合我們。
Tank.update({ _id: id }, { $set: { size: 'large' }}, callback);
如果我們想要應用程序中返回document,有一個更好的選項
Tank.findByIdAndUpdate(id, { $set: { size: 'large' }}, function (err, tank) {
if (err) return handleError(err);
res.send(tank);
});
靜態方法findAndUpdate/Remove 最多只改變一個document,並只通過一個調用返回到數據庫。在 findAndModifu 主題 有 幾 種 變化。閱讀API文檔查看更多細節。注意findAndUpdate/Remove在修改數據庫前不執行任何鈎子或驗證。如果你想要鈎子和驗證,先檢索 document 然后保存它。
3、驗證
document在保存前進行驗證。詳情閱讀API文檔或validation節。
子文檔
sub-document是各自有着schema的document,是一個父元素數組的元素。
var childSchema = new Schema({ name: 'string' }); var parentSchema = new Schema({ children: [childSchema] })
sub-document享有所有與普通document相同的特征。唯一不同的是它們不單獨保存,當它們的頂層父document保存時它們才被保存。
var Parent = mongoose.model('Parent', parentSchema); var parent = new Parent({ children: [{ name: 'Matt' }, { name: 'Sarah' }] }) parent.children[0].name = 'Matthew'; parent.save(callback);
如果在子文檔中間件發生錯誤,它冒泡到父的save()回調,因此錯誤處理是小事一樁。
childSchema.pre('save', function (next) {
if ('invalid' == this.name) return next(new Error('#sadpanda'));
next();
});
var parent = new Parent({ children: [{ name: 'invalid' }] });
parent.save(function (err) {
console.log(err.message) // #sadpanda
})
1、查找子文檔
每一個document都有_id,.DocumentArrays有特殊的 id 方法來通過_id來查找document。
var doc = parent.children.id(id);
2、增加子文檔
mongoose數組方法如push、unshift、addToSet等將參數顯式轉換成恰當的類型。
var Parent = mongoose.model('Parent'); var parent = new Parent; // create a comment parent.children.push({ name: 'Liesl' }); var subdoc = parent.children[0]; console.log(subdoc) // { _id: '501d86090d371bab2c0341c5', name: 'Liesl' } subdoc.isNew; // true parent.save(function (err) { if (err) return handleError(err) console.log('Success!'); });
子文檔的創建不需通過使用創建方法MongooseArrays添加到數組。
var newdoc = parent.children.create({ name: 'Aaron' });
3、刪除文檔
每個子文檔都有自己的刪除方法:
var doc = parent.children.id(id).remove(); parent.save(function (err) { if (err) return handleError(err); console.log('the sub-doc was removed') });
交替聲明語法
如果你不需要訪問的子文檔schena的實例,你也可以通過簡單傳遞一個對象字面量聲明子文檔。
var parentSchema = new Schema({ children: [{ name: 'string' }] })
簡單嵌入子文檔
New in 4.2.0
你還可以在不使用數組的方式下嵌入schema。
var childSchema = new Schema({ name: 'string' }); var parentSchema = new Schema({ child: childSchema });
一個嵌入式子文檔的行為類似於一個嵌入式數組。當它的父文檔保存時它才保存、它的前/后document中間件被執行。
childSchema.pre('save', function(next) {
console.log(this.name); // prints 'Leia'
});
var Parent = mongoose.model('Parent', parentSchema);
var parent = new Parent({ child: { name: 'Luke' } })
parent.child.name = 'Leia';
parent.save(callback); // Triggers the pre middleware.
defaults
1、在schema中聲明默認值
你可以給schema的某些path定義默認值。如果你創建的新document沒有設置那個path,默認值會取代。
var schema = new Schema({ name: String, role: {type: String, default: 'guitarist'} }); var Person = db.model('Person', schema); var axl = new Person({name: 'Axl Rose', role: 'singer'}); assert.equal(axl.role, 'singer'); var slash = new Person({name: 'Slash'}); assert.equal(slash.role, 'guitarist');
2、默認函數
你還可以將默認schema選項設置為一個函數。mongoose 將執行那個函數並使用它的返回值作為默認值。
var schema = new Schema({ title: String, date: { type: Date, // `Date.now()` returns the current unix timestamp as a number default: Date.now } }); var BlogPost = db.model('BlogPost', schema); var post = new BlogPost({title: '5 Best Arnold Schwarzenegger Movies'}); // The post has a default Date set to now assert.ok(post.date.getTime() >= Date.now() - 1000); assert.ok(post.date.getTime() <= Date.now());
3、setDefaultsOnInsert 選項
默認情況下,mongoose只在創建新document時應有默認值。如果你使用update() 和 findOneAndUpdate()它不會設置默認值。可是 mongoose 4.x 讓你選擇性加入這個行為使用 setDefaultsOnInsert 選項。
4、重要
setDefaultsOnInsert 選項依賴MongoDB $setOnInsert 操作符。在 MongoDB 2.4中介紹了$setOnInsert操作符,如果你使用的MongoDB服務器<2.4.0,不要使用setDefaultsOnInsert。
var schema = new Schema({ title: String, genre: {type: String, default: 'Action'} }); var Movie = db.model('Movie', schema); var query = {}; var update = {title: 'The Terminator'}; var options = { // Return the document after updates are applied new: true, // Create a document if one isn't found. Required // for `setDefaultsOnInsert` upsert: true, setDefaultsOnInsert: true }; Movie. findOneAndUpdate(query, update, options, function (error, doc) { assert.ifError(error); assert.equal(doc.title, 'The Terminator'); assert.equal(doc.genre, 'Action'); });
