Javascript find()方法返回具有不需要的属性的对象
所以,我和猫鼬合作了一段时间,发现了一些非常奇怪的事情。如果有人能启发我,那就太好了 问题是,当使用mongoose的.find()方法时,作为响应得到的对象充满了属性,我不知道这些属性来自何处(我猜它们是内置属性,但不管怎样),我只想遍历属性I.select()。知道了?不好啊更好地解释: 我声明了我的模式和模型:Javascript find()方法返回具有不需要的属性的对象,javascript,node.js,mongoose,properties,Javascript,Node.js,Mongoose,Properties,所以,我和猫鼬合作了一段时间,发现了一些非常奇怪的事情。如果有人能启发我,那就太好了 问题是,当使用mongoose的.find()方法时,作为响应得到的对象充满了属性,我不知道这些属性来自何处(我猜它们是内置属性,但不管怎样),我只想遍历属性I.select()。知道了?不好啊更好地解释: 我声明了我的模式和模型: var mySchema = mongoose.Schema({ name: String, prop1: String, prop2: String, prop3
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])日志
到目前为止,一切顺利。但问题是,现在我想迭代这些属性并逐个检查,我不确定每个结果会有多少“道具”,所以我想做一些类似的事情:
for(var key in results[0]){
log(key)
}
所以,我希望它会记录“prop1”、“prop2”和“prop3”,但不会!好的,我得到了道具1、2和3,但我也得到了许多其他属性和函数,如:isNew、error、_maxListeners、_doc等。不仅这些额外属性,我还得到了“name”属性,我从选择中排除的属性(它被排除,如第一个日志所示)。奇怪吧
但是等等!还有更多!我在网上搜索了一下,发现有人说:“伙计,当遍历对象属性时,使用hasOwnProperty方法!”。于是我去了:
for (var key in results[0]){
if (results[0].hasOwnProperty(key)) log(key)
}
日志结果是一些属性(具体来说:$\uuuuuuuu、isNew、error、\u maxListeners、\u doc、\u pres、\u posts、save、\u events),不包括我最初想要的任何道具
我的问题是,我怎么能只遍历prop 1、2和3,不包括这些我不知道的内置属性和我在参数中明确排除的属性?(注:我正在考虑一个解决方案,如果可能的话,它不需要将我的对象转换成数组)
此外,这本身不是一个问题,但出于好奇,这些属性从何而来?为什么它们出现在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
是一个很好的选择,因为它跳过了整个过程,提高了查询速度 答案非常好,我想添加一个我添加到dbUtils类中的小typescript实用程序
getCleanObjectFromObjectOrDocument<T>(obj: T): T {
return ((obj as unknown) as Document)?.toObject?.() ?? obj;
}
getCleanObjectFromObjectOrDocument(obj:T):T{
返回((对象未知)为文档)?.toObject?(对象);
}
您可以在此处传递mongoose文档/子文档或任何普通JS对象,它将返回相应的JS对象。对mongo查询使用lean()或传递{lean:true}参数
例如
myModel.find().lean()
.toObject()会给你一个普通的对象,也许会有帮助?额外的属性是因为您处理的是模型的实例,而不是普通对象。谢谢@Kevin B!还有很多问题,但这确实解决了我的问题!把你的评论作为答案贴出来,这样我就可以把它标记正确了?比尔!那么,我的下一个问题是——我如何才能伪造这些“隐藏”属性进行测试?非常感谢。我不得不对每个结果JSON.parse(JSON.stringify(results))
。使用.toObject()
在各个方面都非常干净和更好。转换为JSON和反向工作的原因也是因为它只是这个.toObject()
方法的别名,所以序列化格式只包含精益对象。我试着运行wait myModel.find({status:'requested'},{lean:true})代码>但它不起作用。我必须以等待myModel.find({status:'requested'}.lean().exec()的形式运行它代码>以使其工作。知道为什么吗?是因为{lean:true}
只能作为find()
调用的第三个参数出现吗?是的,我也遇到了这个问题<代码>等待模型。查找({status:'requested'},{},{lean:true})
通过{lean:true}
为我解决了一个类似的问题。
getCleanObjectFromObjectOrDocument<T>(obj: T): T {
return ((obj as unknown) as Document)?.toObject?.() ?? obj;
}