如何将Mongoose文档转换为普通对象?


200

我有一个猫鼬的文档,我想在JSON编码之前进行扩展并作为响应发送出去。如果我尝试向文档添加属性,则将其忽略。该属性不会出现无法Object.getOwnPropertyNames(doc)进行正常扩展的情况。奇怪的是,它JSON.parse(JSON.encode(doc))可以正常工作并返回具有所有正确属性的对象。有一个更好的方法吗?

Answers:


291

猫鼬Model继承自Documents,后者有一个toObject()方法。我相信您要寻找的应该是的结果doc.toObject()

http://mongoosejs.com/docs/api.html#document_Document-toObject


1
终于明白了。对于那些未定义toObject的对象,请确保调用文档而不是模型。即modelName._doc.toObject()
约翰

1
可以,但首选lean()。
杰森·塞布林

如果您Model.find({})在docs返回数组时返回数组,这是否可行?您可以docs.toObject吗?
杰克·

5
@jackblank,如果您有一组模型,则应该可以在它们上进行映射:var docArray = modelArray.map(function(model) { return model.toObject(); });
jmar777

@ jmar777我认为您的建议属于对此答案的修改。
r3wt

200

执行此操作的另一种方法是,通过使用以下命令告诉Mongoose,您所需要的只是返回文档的纯JavaScript版本 lean()在查询链中,。这样,Mongoose跳过了创建完整模型实例的步骤,您直接获得一个doc可以修改的对象:

MyModel.findOne().lean().exec(function(err, doc) {
    doc.addedProperty = 'foobar';
    res.json(doc);
});

16
@Startec使用lean通常性能更高,因为您跳过了首先创建完整的Mongoose文档的开销。
JohnnyHK

3
您是拥护者:)如果我错了,请纠正我,但是如果您不打算修改和保存刚收到的文档,则应该始终lean()您的find()(例如,如果您只是尝试访问doc并将其发送回客户)
Amarsh

1
@Amarsh是的,尽管这还假设您不需要架构中定义的任何实例方法或虚函数。
JohnnyHK

1
奇怪的是...这可能是find()的选择...它通常太常见,无法从mongodb中读取文档并将其发送回Web浏览器。我想知道find()。lean()是否首先实际意味着find(),然后在结果中应用每个元素的lean(),在这种情况下,find()。lean()的组合实际上会比find()慢本身。
Amarsh

4
@Amarsh否,lean()在查询上实际执行(通过exec)之前,在查询上链接会设置选项,以便结果直接以其“精简”形式显示。有关呼叫对性能的积极影响,请参阅此问题lean
JohnnyHK

29

如果属性不在模型中的快速方法:

document.set( key,value, { strict: false });


5
是的...虽然看起来令人惊讶,但我仍然认为这可能很有用。例如,保留所有对象的原语。
alban maillere 2014年

感谢您的答复,这就是我想要的东西:)
datUser

6

解决这样的问题的一个更好的办法是使用doc.toObject()这样的

doc.toObject({ getters: true })

其他选项包括:

  • getters: 应用所有吸气剂(路径和虚拟吸气剂)
  • virtuals: 应用虚拟吸气剂(可以覆盖吸气剂选项)
  • minimize: 删除空对象(默认为true)
  • transform: 返回之前应用于结果文档的转换函数
  • depopulate: 取消填充所有路径,将其替换为原始引用(默认为false)
  • versionKey: 是否包含版本密钥(默认为true)

例如,你可以说

Model.findOne().exec((err, doc) => {
   if (!err) {
      doc.toObject({ getters: true })
      console.log('doc _id:', doc._id)
   }
})

现在它将起作用。

有关参考,请参阅:http : //mongoosejs.com/docs/api.html#document_Document-toObject


3

为了从猫鼬文档中获取普通对象,我使用_doc了如下属性

mongooseDoc._doc  //returns plain json object

我尝试过,toObject但是它给了我不需要的功能,参数和所有其他东西。


3
首先访问属性或方法 _不是理想的解决方案。使用精益可能会解决您的问题。
亚瑟·科斯塔

@ArthurBrito是的。它不是理想的解决方案,但仍然是解决方案!。无需拒绝投票。我已经_doc多次使用财产而没有遇到任何问题。并且using lean方法为您提供了无法执行猫鼬模型操作的简单对象。
dd619 '19

你是对的。只要添加您的答案,那不是理想的解决方案,然后我将删除不推荐使用的选票(除非您进行了编辑,否则我将无法删除)
Arthur Costa

2

您还可以对对象进行字符串化,然后再次解析以生成普通对象。例如:

const obj = JSON.parse(JSON.stringify(mongoObj))
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.