mongoose .find() 方法返回具有不需要的属性的对象

Posted

技术标签:

【中文标题】mongoose .find() 方法返回具有不需要的属性的对象【英文标题】:mongoose .find() method returns object with unwanted properties 【发布时间】:2015-04-11 03:35:00 【问题描述】:

所以,我已经和猫鼬一起工作了一段时间,我发现发生了一些非常奇怪的事情。如果有人能启发我,那就太好了。

问题是,当使用猫鼬的 .find() 方法时,我得到的响应对象充满了我不知道它来自哪里的属性(我猜它们是内置属性,但是无论如何),我只想遍历我.select()的属性。知道了?不?好的...解释得更好:

我声明了我的架构和模型:

var mySchema = mongoose.Schema(
  name: String,
  prop1: String,
  prop2: String,
  prop3: String
)
var myModel = DB.model('myDataBase', mySchema)

然后我想找到一个名称为 John 的文档,并检索除“name”字段之外的所有字段,所以我去:

myModel.find(name: 'John', '-name', function(err, results)
  log(results[0])

和日志(结果[0])日志

 prop1: 'one',
  prop2: 'two',
  prop3: 'three' 

到目前为止,一切都很好。但问题是,现在我想遍历这些属性并一一检查,我不确定每个结果会有多少“道具”,所以我想做类似的事情:

for(var key in results[0])
  log(key)

所以,我希望它会记录“prop1”、“prop2”和“prop3”,但没有!好的,我得到了 props 1、2 和 3,但我还得到了许多其他属性和函数,例如:isNew、error、_maxListeners、_doc 等。不仅这些额外属性,我还得到了 'name' 属性,我从选择中排除的一个(它被排除在外,如第一个日志中所示)。很奇怪吧?

但是等等!还有更多!我在网上搜索过,发现有人说“老兄,在遍历对象属性时使用 hasOwnProperty 方法!”。所以我去了:

for (var key in results[0])
  if (results[0].hasOwnProperty(key)) log(key)

日志结果是一些属性(具体来说:$__、isNew、error、_maxListeners、_doc、_pres、_posts、save、_events)并且不包括我想要的任何道具。

我的问题是,我怎样才能只遍历道具 1、2 和 3,不包括这些,我不知道,内置属性和我在参数中明确排除的属性? (ps:如果可能的话,我正在考虑一个不需要将我的对象转换为数组的解决方案)

另外,这本身不是一个问题,但出于好奇,这些属性从何而来?为什么它们出现在 for 循环中而不是在我记录对象时出现?为什么我排除的属性('-name')也出现在 for 循环中?如果 hasOwnProperty 不能识别刚刚记录的属性,那它到底是为了什么?

感谢您的时间和帮助! 再见!

【问题讨论】:

.toObject() 会给你一个普通的对象,也许这会有所帮助?额外的属性是因为您正在处理的是模型的一个实例,它不是一个普通的对象。 感谢@Kevin B!还有很多问题,但这确实解决了我的问题!发表您的评论作为答案,以便我可以标记它吗? BR! 【参考方案1】:

除了 Kevin B 的回答,您也可以通过 lean: true 作为选项:

myModel.find(name: 'John', '-name', lean: true, function(err, results)
  log(results[0])

在 MongoDB 中,文档被简单地保存为对象。当 Mongoose 检索它们时,它会将它们转换为 Mongoose 文档。这样做时,它会添加所有包含在 for 循环中的键。这就是允许您使用所有文档方法的原因。如果您不使用其中任何一个,lean 是一个不错的选择,因为它会跳过整个过程,从而提高查询速度。 Potentially 3x as fast.

【讨论】:

我尝试运行await myModel.find(status: 'requested', lean: true);,但没有成功。我必须以await myModel.find(status: 'requested').lean().exec(); 运行它才能让它工作。知道为什么吗?是因为lean: true 只能作为find() 调用的第三个参数吗? 是的,我也遇到了这个问题。 await Model.find(status:'requested', ,lean:true) 通过lean:true 为我解决了类似的问题。【参考方案2】:

在这种情况下,.toObject 足以让您的循环按您期望的方式工作。

myModel.find(name: 'John', '-name', function(err, results)
  log(results[0].toObject())

您最初获得的额外属性是由于results 是模型实例的集合,这些实例带有普通对象不可用的额外属性和方法。这些属性和方法是循环中出现的。通过使用toObject,您可以获得一个没有所有这些额外属性和方法的普通对象。

【讨论】:

我的下一个问题,然后 - 我怎样才能欺骗这些“隐藏”属性进行测试? 非常感谢。每个结果我都必须JSON.parse(JSON.stringify(results))。使用.toObject() 在各个方面都更干净、更好。 转换为JSON并返回的原因是因为document object’s .toJSON() method只是这个.toObject()方法的别名,所以序列化格式只包含精益对象。【参考方案3】:

答案很好,我想添加一个我添加到我的 dbUtils 类的小打字稿实用程序。

getCleanObjectFromObjectOrDocument<T>(obj: T): T 
        return ((obj as unknown) as Document)?.toObject?.() ?? obj;

您可以在此处传递 mongoose 文档/子文档或任何普通 JS 对象,它会返回相应的 JS 对象。

【讨论】:

【参考方案4】:

在 mongo 查询上使用lea() 或传递 lean:true 参数 例如myModel.find().lean()

【讨论】:

以上是关于mongoose .find() 方法返回具有不需要的属性的对象的主要内容,如果未能解决你的问题,请参考以下文章

更新 findOne()/find()/findById() 返回的文档 - mongoose

更新 findOne()/find()/findById() 返回的文档 - mongoose

为什么在mongoose中使用find方法时console.log返回空数组?

未找到结果时如何从 Mongoose Find 查询返回自定义消息而不是空数组

Mongoose:.find() 不返回任何文档

mongoose.find() 每次都不返回