解决Mongoose 返回的文档过大导致模板引擎art-template无法渲染的问题,错误-RangeError: Maximum call stack size exceeded

参考:https://blog.csdn.net/qq_40659195/article/details/88411838

最近尝试用Node写一个小案例,使用到了MongoDB,使用过的人可以知道,Node-js操作MongoDB的官方包实在有些麻烦,为了方便开发,使用了mongoose这样的一个中间插件,但是却发现,查询的数据无法通过art-template渲染(注: 这里使用的express框架,通过express配置的art-template),结果报错:

Maximum call stack size exceeded
at Buffer.get [Symbol.toStringTag] ()
at Buffer.toString ()

根据问题描述,应该是内存问题,按照我的性格,当然先百度一下(有谷歌的通知勿喷,最近FQ老是出问题),大多数写的都是递归造成的问题描述,我靠,这和我情况一毛钱关系没有,故转而还是自己想办法,经过一番折腾,发现,只有mongoose返回的文档对才会导致该问题,如果自己定义的JSON数据或者对象的数据都没有这样的情况,果断得出结果------是mongoose返回文档对象太过庞大造成,然后又折腾了一番,toString,对象拷贝,都没有成功,因为文档对象是不可变的(这句话现在是有些正确的,尽管还没有绝对的证据)!最后按照JSON格式数据操作一番,

先通过JSON.stringify()这个方法将文档对象转为字符串,将他的其他属性全部格式掉,只需要留下需要的数据字符串即可!

然后再通过JSON.parse()这个方法转为对象,这个方法虽然丢失效率,但是暂时解决问题,后面有更好的解决方案或者楼主得到了原因会更新解决方法和方案!代码附上,希望了解该问题的大神能提点一二!

评论区解决方案引申:

可以在查询链上使用lean()。告诉mongoose返回普通对象 不返回mongoose文档对象

我的最终解决方案:

// 解决方案1:
// 使用lean()
// let result = await Article.find({}).populate('author').lean();

// 解决方案2:
// 如果使用了第三方模块mongoose-sex-page控制查询数据,则不能使用lean()。
// 导入第三方模块mongoose-sex-page控制分页查询的数据
const pagination = require('mongoose-sex-page');
let result = await pagination(Article).page(1).size(4).display(5).find({}).populate('author').exec();

result = JSON.stringify(result);
result = JSON.parse(result); 

知识扩展:

参考:Mongoose - lean
Faster Mongoose Queries With Lean

默认情况下,Mongoose查询返回Mongoose Document类的实例。 文档比普通的JavaScript对象重得多,因为它们具有很多用于跟踪更改的内部状态。 启用lean选项会告诉Mongoose跳过实例化完整的Mongoose文档,只给您POJO。

lean属性的作用:跳过转换为MongooseDocuments类型,直接返回JS Object,从而便于我们修改查询结果。

mongoose查询:

  • Model.findOne({});
  • Model.save();

以上2种查询返回的数据实际上是Mo

ngooseDocuments对象(mongoose自己封装的一个对象),并且这个对象会对数据进行实时查询以保证其符合预定义的model。所以添加其它model中没有的属性时是无法添加成功的。

要想添加成功有2种方法:

  1. 查询时添加lean,
  • Model.findOne({}).lean();
  • Model.findOne({lean:true},function(err,result){});
  • Model.findOne({}).lean().exec(function(err,result){});
  1. 将查询结果转为object,查询结果result.toObject();
posted @ 2020-08-25 16:23  JaceyKan  阅读(892)  评论(1编辑  收藏  举报