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

res*_*ode 186 mongoose node.js

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

jma*_*777 261

Mongoose Models继承自Documents,它有一个toObject()方法.我相信你所寻找的应该是你的结果doc.toObject().

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

  • 终于得到了。对于那些没有定义 toObject 的人,请确保调用文档而不是模型。即模型名称._doc.toObject() (4认同)
  • toObject undefined (3认同)
  • 这没问题,但最好使用 Lean()。 (3认同)
  • 如果您在`Model.find({})` 上返回数组,这是否有效,文档返回的是一个数组。你可以 docs.toObject 吗? (3认同)
  • @jackblank如果你有一个模型数组,那么你应该可以映射它们:`var docArray = modelArray.map(function(model){return model.toObject();});` (3认同)
  • 不适合我.下面的解决方案确实如此. (2认同)

Joh*_*yHK 188

另一种方法是告诉Mongoose,通过lean()在查询链中使用,您所需要的只是返回文档的纯JavaScript版本.那样Mongoose就会跳过创建完整模型实例的步骤而你直接得到一个doc你可以修改的:

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

  • toObject对我不起作用.精益()是完美的 (14认同)
  • @Startec使用`lean`通常更高效,因为您跳过了首次创建完整Mongoose文档的开销. (13认同)
  • @Amarsh不,在查询上链接`lean()`在实际执行查询之前设置选项(由`exec`),以便结果直接以其"精简"形式.请参阅[此问题](http://stackoverflow.com/questions/15097375/mongoose-node-js-module-causes-high-cpu-usage),了解调用"精益"的积极性能影响方面. (4认同)
  • 你是冠军:)纠正我,如果我错了,但你应该总是瘦()你发现()秒,如果你不打算修改并保存您刚刚收到(比如文档,如果你只是想访问doc并将其发回给您的客户) (3认同)

alb*_*ere 25

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

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

  • 是的......虽然看起来很惊人,但我仍然认为这可能是有用的.例如,您保留所有对象的基元. (4认同)

adi*_*gil 15

JohnnyHK 建议:

在@JohnnyHK 建议的某些情况下,您可能希望将对象作为普通 Javascript 获取。如本Mongoose 文档中所述,还有另一种方法可以将数据直接作为对象进行查询:

const docs = await Model.find().lean();
Run Code Online (Sandbox Code Playgroud)

有条件地返回普通对象:

此外,如果有人可能想有条件地转向一个对象,也可以将其作为option参数,请参阅find() 文档中的第三个参数:

const toObject = true;
const docs = await Model.find({},null,{lean:toObject});
Run Code Online (Sandbox Code Playgroud)

其可使用功能:find()findOne()findById()findOneAndUpdate(),和findByIdAndUpdate()

笔记:

还值得一提的是,该_id属性不是字符串对象,就像您会做的那样,JSON.parse(JSON.stringify(object))而是来自猫鼬类型的 ObjectId,因此在将其与字符串进行比较时,将其转换为之前的字符串:String(object._id) === otherStringId


Jal*_*sem 11

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

doc.toObject({ getters: true })
Run Code Online (Sandbox Code Playgroud)

其他选项包括:

  • 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)
   }
})
Run Code Online (Sandbox Code Playgroud)

现在它会起作用了。

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


小智 8

精益选项告诉 Mongoose 跳过对结果文档进行水合处理。这使得查询速度更快,内存占用更少,但结果文档是普通的旧 JavaScript 对象 (POJO),而不是 Mongoose 文档。

const leanDoc = await MyModel.findOne().lean();
Run Code Online (Sandbox Code Playgroud)

不需要使用 JSON.parse() 方法


kau*_*_pm 6

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

const obj = JSON.parse(JSON.stringify(mongoObj))
Run Code Online (Sandbox Code Playgroud)


dd6*_*619 5

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

mongooseDoc._doc  //returns plain json object
Run Code Online (Sandbox Code Playgroud)

我试过了,toObject但它给了我函数、参数和所有其他我不需要的东西。

  • 在开头使用“_”访问属性或方法并不是理想的解决方案。使用精益可能会解决您的问题。 (4认同)