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

mongoose .find() method returns object with unwanted properties

所以,我使用 mongoose 已经有一段时间了,我发现了一些非常奇怪的事情。如果有人能开导我就太好了。

问题是,当使用猫鼬的 .find() 方法时,我作为响应获得的对象充满了我不知道它来自哪里的属性(我猜它们是内置属性,但无论如何)我只想遍历属性 I .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' }

到目前为止,还不错。但问题是,现在我想遍历这些属性并一一检查,但我不确定每个结果会有多少 'props',所以我想做类似的事情:

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

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

但是等等!还有更多!我在网上搜索了一下,发现有人说 "Dude, when iterating through object properties use the hasOwnProperty method!"。所以我去了:

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

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

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

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

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

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

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

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

对于 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.

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

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

您可以在此处传递 mongoose document/sub-document 或任何普通 JS 对象,它会 return 一个相应的 JS 对象。

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