以前接手了一個微信公衆號的項目,項目的技術棧是: NodeJs
+ExpressJs
+mongo
+mongoose
+jade
,第一次使用ODM(Object DatabaseManage)工具mongoose
,發現使用起來仍是很是方便的,你能夠預先定義一個model
,把mongo這種NoSql當作關係型數據庫使用,而且經過populate
能基本實現一些比較簡單的鏈接查詢 ,可是在使用的過程當中也是踩了很多坑,舉例講一個比較典型的:對於mongoose返回數據的修改的問題。
假設咱們須要涉及一個關於評論的model
,咱們用下面的代碼舉例:javascript
var mongoose = require('mongoose'); var Schema = mongoose.Schema; var CommentSchema = new Schema({ topicId: {type: Schema.ObjectId, ref:'Topic',index: true}, author: { type: Schema.ObjectId, ref: 'User'}, group: {type: Number, default: 0, index: true}, content: String, status: {type: Number, default: 0}, createdAt: { type: Date, default: Date.now }, favNum: {type:Number, default: 0} }); var Comment = mongoose.model('Comment', CommentSchema); module.exports = Comment;
上面的代碼很是的簡單明瞭,定義了model
的各類字段、類型、引用,這樣咱們在代碼中就能夠經過mongoose對mongo進行查詢了,有Java的經驗老司機會發現這個工具和Hibernate
很是類似。
假設如今咱們有一個業務,我須要提供一個Restful Get接口,返回當前文章的評論信息,而且根據session判斷登陸用戶,去對每條評論判斷是否該登陸用戶已經點贊,那麼我想要在返回的數據中臨時增長一個字段isPraise
,true
表明是當前登陸用戶已經點贊,false
表明當前用戶未點贊。
咱們可能會有下面兩種mongoose的代碼風格java
Comment.findOne({ id: commentId, },function (err,data) { if(){ //若是用戶點贊 data.isPraise = true; }else{ //若是用戶未點贊 data.isPraise = false; } });
或者數據庫
Comment.findOne({ id: commentId }).exec(function (err,data) { if(){ //若是用戶點贊 data.isPraise = true; }else { //若是用戶未點贊 data.isPraise = false; } });
上面的代碼看起來沒有任何的問題,mongoose返回的是Object,我根據本身的業務新增屬性,而後以JSON數據返回給用戶。可是事實上新增長的屬性不能被打印出來(經過console.log(JSON.stringify(data))
)也不能返回給客戶端,可是奇怪的是卻能夠打印出來console.log(data.isPraise)
,並且Object.prototype.hasOwnProperty()
方法返回的也是true
,說明確實已經增長了這個屬性,爲何不會返回給請求方呢?
後面通過排查終於發現了問題的所在,實際上mongoose返回的數據並非object
,雖然你經過typeof
判斷類型是object
,其實是mongoose本身封裝的一個對象,而且這個對象會對數據進行實時查詢以保證其符合預約義的model
,由於model
中壓根就沒有isPraise
屬性,因此是沒法增長的。
如今看來解決方法能夠在model
中預先定義isPraise
字段,可是這個並非沒有業務都須要的,因此這種方法太糙了,果斷放棄。幸虧mongooes提供給咱們函數來解決這個問題:lean()
。代碼以下:微信
Comment.findOne({ id: commentId, },null,{ lean: true }function (err,data) { if(){ //若是用戶點贊 data.isPraise = true; }else{ //若是用戶未點贊 data.isPraise = false; } });
或者session
Comment.findOne({ id: commentId }).lean().exec(function (err,data) { if(){ //若是用戶點贊 data.isPraise = true; }else { //若是用戶未點贊 data.isPraise = false; } });
經過上述方法就能夠解決mongoose對返回數據的控制了,你就能夠隨心所欲了,固然若是不是這種業務,儘可能建議少使用,畢竟最好仍是使數據符合預先定義的model
比較好。mongoose