之前接手了一个微信公众号的项目,项目的技术栈是: NodeJs
+ExpressJs
+mongo
+mongoose
+jade
,第一次使用ODM(Object DatabaseManage)工具mongoose
,发现使用起来还是非常方便的,你可以预先定义一个model
,把mongo这种NoSql当做关系型数据库使用,并且通过populate
能基本实现一些比较简单的连接查询 ,但是在使用的过程中也是踩了不少坑,举例讲一个比较典型的:对于mongoose返回数据的修改的问题。
model
,我们用下面的代码举例: 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
非常相似。
isPraise
,true
代表是当前登录用户已经点赞,false
代表当前用户未点赞。 我们可能会有下面两种mongoose的代码风格 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
,说明确实已经增加了这个属性,为什么不会返回给请求方呢?
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; }});
或者
Comment.findOne({ id: commentId}).lean().exec(function (err,data) { if(){ //如果用户点赞 data.isPraise = true; }else { //如果用户未点赞 data.isPraise = false; }});
通过上述方法就可以解决mongoose对返回数据的控制了,你就可以为所欲为了,当然如果不是这种业务,尽量建议少使用,毕竟最好还是使数据符合预先定义的model
比较好。