微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Mongoose中document与object的区别示例详解

前言

本文主要给大家总结介绍了关于Mongoose中document与object区别的相关内容分享出来供大家参考学习,其实这个问题其实是mongoose非常常见的问题,经常有很多以前没遇到这个问题的人都会被这个问题弄得怀疑人生。

我们先介绍一些问题的背景。

先看下面一段代码

{ res.render('index',{ title: 'express',docs: docs }) }) });
rush:xhtml;"> <%= title %>

<%= title %>

Welcome to <%= title %>

    <% docs.forEach(function(doc){ %>
  • <%= doc.type %>
  • <% }) %>

在第一段代码中,通过model.find我们应该能够获取到根据queryCriteria获取的结果,结果应该是一个对象数组,类似于这样:

rush:plain;"> [{ "_id" : ObjectId("59bdeadb2a5c612514ee7970"),"title" : "好楼层,中等装修,满5年,上门实拍","type" : "2室1厅","square" : "75.42平","direction" : "朝南","floor" : "中区/6层","unitPrice" : 47732,"totalPrice" : 360,"location" : null,"specialExplain" : "满五","url" : "http://sh.lianjia.com//ershoufang/sh4528035.html","station" : "江杨北路","line" : "3号线","updateTime" : "2017-09-17 11:24:11" } { "_id" : ObjectId("59bdeadb2a5c612514ee7971"),"title" : "南北户型,厨卫全明,高区采光好,装修精美","type" : "2室2厅","square" : "90.92平","direction" : "朝南北","floor" : "高区/6层","unitPrice" : 46194,"totalPrice" : 420,"url" : "http://sh.lianjia.com//ershoufang/sh4546221.html","updateTime" : "2017-09-17 11:24:11" }]

预期index.ejs应该渲染的页面一个ul渲染的结果,类似于

  • 2室1厅
  • 2室2厅

当然,理想很丰满,现实很骨感。我就是死活渲染不出来doc.type。照理说应该是不可能的,在index.ejs中doc就是一个对象,我为什么不能获取doc的type属性呢?这不合理,太不合理了!

老实说,这个问题我之间也是遇到过,当初我是想修改这个doc的属性,但是死活没有办法修改,当初也是花了很久找到原因。这次我就把这个问题好好地研究一下。

先说结果,以及解决方法把。我比较喜欢剧透。愿意是因为再次返回的doc是属于Document的实例,而不是一个普通的对象。也就是说它和普通的对象是不一样的,它没有普通对象的一些方法,普通对象也没有它身上的一些方法

解决方案有几种,不过究其根本都是将这种document转化为普通的对象:

方法1:

利用nofollow" target="_blank" href="http://mongoosejs.com/docs/api.html#document_Document-toObject">toObject方法

{ return doc.toObject(); })

方法2:

利用JSON方法,这是我想到的一个方法,具体深层原因在这就不展开了:

rush:js;"> docs = JSON.stringify(docs); docs = JSON.parse(docs);

方法3:

利用lean方法

{ .... })

上述的三种方法应该都能成功将find获取的结果转化为普通的对象。

但是我还想知道到底document和一个普通的对象到底有什么区别,区别在哪里呢?

我们假设find获取的结果是docs,转化为普通对象的结果是docs1。现在我们就看一看这二者的区别。理论上docs和docs1都应该是数组,而它们中元素都应该是一个对象,我们先来看看是不是这样呢?

rush:js;"> console.log(Object.prototype.toString.call(docs)); consoele.log(Object.prototype.toString.call(docs[0]));

console.log(Object.prototype.toString.call(docs1));
console.log(Object.prototype.toString.call(docs1[0]))

我们通过上述方法可以获取docs以及docs1的类型以及其中元素的类型,结果是:

rush:js;"> [object Array] [object Object]

[object Array]
[object Object]

和我们预想中的一模一样,那问题不在这,那我们就探究探究docs[0]以及docs1[0]的原型把,看看它的原型到底是什么呢?知道JS的人,应该都知道JS中的原型链。在此,我们就通过__proto__来粗暴地获取对象的原型:

rush:js;"> console.dir(doc[0].__proto__);

console.dir(docs[0].proto);

结果是:

rush:js;"> model { db: NativeConnection { base: Mongoose { connections: [Array],models: [Object],modelSchemas: [Object],options: [Object],plugins: [Array] },collections: { realestates: [Object] },models: { realestate: [Object] },config: { autoIndex: true },replica: false,hosts: null,host: '127.0.0.1',port: 27017,user: undefined,pass: undefined,name: 'real_estate_info',options: { db: [Object],auth: {},server: [Object],replset: [Object],mongos: undefined },otherDbs: [],_readyState: 1,_closeCalled: false,_hasOpened: true,_listening: false,db: Db { domain: null,_events: [Object],_eventsCount: 6,_maxListeners: undefined,s: [Object],serverConfig: [Getter],bufferMaxEntries: [Getter],databaseName: [Getter],_listening: true },_events: { connected: [Function],error: [Function: bound bound consoleCall],disconnected: [Function: bound bound consoleCall],reconnected: [Function: bound bound consoleCall] },_eventsCount: 4 },discriminators: undefined,id: [Getter/Setter],__v: [Getter/Setter],_id: [Getter/Setter],schema: Schema { obj: undefined,paths: { _id: [Object],__v: [Object] },aliases: {},subpaths: {},virtuals: { id: [Object] },singlenestedpaths: {},nested: {},inherits: {},callQueue: [ [Array],[Array],[Array] ],_indexes: [],methods: {},statics: {},tree: { _id: [Object],__v: [Function: Number],id: [Object] },query: {},childSchemas: [],plugins: [ [Object],[Object],[Object] ],s: { hooks: [Object],kareemHooks: [Object] },options: { retainKeyOrder: false,typeKey: 'type',id: true,noVirtualId: false,_id: true,noId: false,validateBeforeSave: true,read: null,shardKey: null,autoIndex: null,minimize: true,discriminatorKey: '__t',versionKey: '__v',capped: false,bufferCommands: true,strict: true,pluralization: true },'$globalPluginsApplied': true,_requiredpaths: [] },collection: NativeCollection { collection: Collection { s: [Object] },opts: { bufferCommands: true,capped: false },name: 'realestates',collectionName: 'realestates',conn: NativeConnection { base: [Object],collections: [Object],config: [Object],db: [Object],queue: [],buffer: false,emitter: EventEmitter { domain: null,_events: {},_eventsCount: 0,_maxListeners: undefined } },'$__original_save': { [Function] numAsyncPres: 0 },save: { [Function: wrappedpointcut] '$originalFunction': '$__original_save','$isWrapped': true },_pres: { '$__original_save': [ [Object],'$__original_remove': [ [Object] ] },_posts: { '$__original_save': [],'$__original_remove': [] },'$__original_remove': { [Function] numAsyncPres: 1 },remove: { [Function: wrappedpointcut] '$originalFunction': '$__original_remove','$__original_validate': [Function],validate: { [Function: wrappedpointcut] '$originalFunction': '$__original_validate','$isWrapped': true } }

以及

rush:js;"> {}

很显然,问题就是在这里,docs[0]和docs[0]的原型并不是一个东西。而js中对象通过.或者是[]访问属性都是调用了Object中的某个方法,但具体什么方法我不太记得。然而docs中的原型或者其原型的原型也是没有这个方法的,因此他就没办法去访问这个属性

其实docs[0].__proto__.__proto__是Model,docs[0].__proto__.__proto__.__proto__是Document,docs[0].__proto__.__proto__.__proto__.__proto__才是{}。

至此,这个问题引起的一系列的探究也是告一段落了。其实Mongoose还有另外一些奇怪的地方,被人所诟病,在此也不一一细数了。从问题的发现,到写这篇文章大概花了大半天的时间,以前遇到问题就找到解决办法就停止了,但是这一次通过这样深入地去发现,可能就会发掘到更多的东西。

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作能带来一定的帮助,如果有疑问大家可以留言交流,谢谢大家对编程之家的支持

原文地址:https://www.jb51.cc/js/36346.html

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐