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

相关文章
相关标签/搜索