虛擬字段並不真實存在於數據庫中,但是在Mongoose文檔中和普通字段中扮演着同樣的角色。
簡單來講,虛擬字段除了不會存入數據庫外,其他方面和普通字段沒有區別。
一、用虛擬字段創建聚合字段是很不錯對選擇。
例如:如果我們的系統需要有姓、名以及全名等字段(全名不過是姓和名連接起來),所以除了姓、名的值不需要再存儲全名的值。
我們需要做的只是在虛擬字段裏將姓和名連接起來。
二、其他用例是使數據庫向下兼容。
例如,我們可能在一個MongoDB集合中有成千上萬的用戶條目,然後我們想收集他們的位置信息。
這時有兩個選擇:
1.一種是運行一個遷移腳本向成千上萬個老的用戶文檔中增加默認的位置信息(none)
2.另一種是運行時使用一個默認配置的虛擬字段。
三、定義一個虛擬字段我們需要:
1.調用virtual(name)方法來創建一個虛擬類型
2.使用get(fn)方法來應用getter函數
例如Gravatar網站:
是一個提供頭像圖片服務的站點。他的URL通常是用戶郵箱的md5加密串。
因此,我們可以通過使用虛擬字段來獲取經過動態散列的gravatarUrl虛擬值,而無需存儲這個值(減輕負載)。
在接下來的例子中,我們故意使輸入的email大小寫混合,同時增加一個空格,然後應用加密:
Identity.virtual('gravatarUrl')
.get(function(){
if(!this.email) return null;
var crypto = require('crypto'),
email = '[email protected] ',
email = email.trim();
email = email.toLowerCase();
var hash = crypto
.createHash('md5')
.update(email)
.digest('hex');
var gravatarBaseUrl = 'https://secure.gravatar.com/avatar/';
return gravatarBaseUrl + hash;
});
之前提到的用例—通過姓、名得到全名,代碼如下:
userSchema.virtual('fullName')
.get(function(){
return this.firstName + ' ' + this.lastName;
})
其他場景是當整個文檔的一個子集是需要暴露的。
如下所示:如果用戶模型有令牌和密碼,我們使用白名單忽略這些敏感的字段,只返回那些我們需要暴露的字段:
userSchema.virtual('info')
.get(function(){
return{
service: this.service,
username: this.username,
name: this.name,
date: this.date,
url: this.url,
avatar: this.avatar
};
});