以前接手了一个微信公众号的项目,项目的技术栈是: 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