Mongoose返回數據修改中遇到的坑

以前接手了一個微信公衆號的項目,項目的技術棧是: 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判斷登陸用戶,去對每條評論判斷是否該登陸用戶已經點贊,那麼我想要在返回的數據中臨時增長一個字段isPraisetrue表明是當前登陸用戶已經點贊,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

相關文章
相關標籤/搜索