将普通对象投射到猫鼬文档
Posted
技术标签:
【中文标题】将普通对象投射到猫鼬文档【英文标题】:Cast plain object to mongoose document 【发布时间】:2014-08-03 03:17:26 【问题描述】:UPDATE 1:已收到 5 票,因此我已提交功能请求:https://github.com/LearnBoost/mongoose/issues/2637
请在那里投你的 +1 票,让核心团队知道你想要这个功能。
更新 2: See answer below...
原帖:
假设我对集合进行“精益”查询或从 REST 服务接收一些数据,然后我得到一个对象数组(不是猫鼬文档)。
这些对象已经存在于数据库中,但我需要将部分/所有这些对象转换为 mongoose 文档以进行单独编辑/保存。
我已经阅读了源代码,一旦 mongoose 从数据库中获取数据(填充、转换、初始化等),就会发生很多事情,但似乎没有一种方法可以将其“公开”给外面的世界。
我正在使用以下内容,但它看起来很老套($data
是一个普通对象):
// What other properties am I not setting? Is this enough?
var doc = new MyModel( $data );
doc.isNew = false;
// mimicking mongoose internals
// "init" is called internally after a document is loaded from the database
// This method is not documented, but seems like the most "proper" way to do this.
var doc = new MyModel( undefined );
doc.init( $data );
更新:经过更多搜索,我认为还没有办法做到这一点,上面的第一种方法是你最好的选择(mongoose v3.8.8)。如果其他人对此感兴趣,我会提出这样的功能请求(请发表评论或投票):
var doc = MyModel.hydrate( $data );
【问题讨论】:
难道不能使用集合中对象上提供的唯一 ID 更新每个单独的文档吗?这样您就不必将对象转换为特定类型,只需更新Model.update(_id : id, ...
这是一个直接到数据库的事务并且绕过了对文档实例的需求。这里的讨论是关于将一个普通的 JS 对象转换为一个完全转换的猫鼬文档,这样我就可以做一些业务逻辑的事情,比如调用自定义方法、手动触发验证等等......
【参考方案1】:
发布我自己的答案,这样就不会保持开放状态:
版本 4 模型(2015 年 3 月 25 日稳定发布)现在公开了一个 hydrate()
方法。最初,所有字段都不会被标记为 dirty,这意味着对 save()
的调用将不会执行任何操作,直到字段发生突变。
https://github.com/LearnBoost/mongoose/blob/41ea6010c4a84716aec7a5798c7c35ef21aa294f/lib/model.js#L1639-1657
需要特别注意的是,它的目的是用于将从数据库加载的纯 JS 对象转换为 mongoose 文档。如果您从 REST 服务或类似服务接收文档,则应使用 findById()
和 update()
。
对于那些生活危险的人:
如果你真的想在不接触数据库的情况下更新现有文档,我想你可以调用hydrate()
,将字段标记为脏,然后调用save()
。这与我在原始问题中建议的设置 doc.isNew = false;
的方法没有太大区别。然而,Valeri(来自 mongoose 团队)建议不要这样做。它可能会导致验证错误和其他极端情况问题,通常不是好的做法。 findById 真的很快,不会成为你的瓶颈。
【讨论】:
【参考方案2】:-
如果您收到来自 REST 服务的响应并说您有一个 User mongoose 模型
var User = mongoose.model('User');
var fields = res.body; //Response JSON
var newUser = new User(fields);
newUser.save(function(err,resource)
console.log(resource);
);
-
在其他情况下,假设您有一组来自 User.find() 要查询或填充的用户 JSON 对象
var query = User.find();
query.exec(function(users)
//mongoose deep-populate ref docs
User.deeppopulate users 'email_id phone_number'.exec(
//query through populated users objects
);
);
MongoDB 不支持连接和传输。所以现在你不能直接将值转换为对象。虽然您可以使用 forEach 解决它。
【讨论】:
你在这里描述了基本的猫鼬东西。您错过的部分是“这些对象已存在于数据库中”。我有一个来自 PUT(更新)请求的普通 javascript 对象。我知道这个对象已经存在于我的数据库中。我想将此对象转换为 mongoose 文档,调用一些自定义方法,然后调用save()
并知道 existing 文档将得到更新。现在的问题突出了解决此问题的最佳方法。
不像在android中你可以强制转换(User) user_object = rawjson object.toString() ...这里你必须在模型中手动编写一个可以被forEach(object)调用的函数->从 json 对象中剥离每个需要的数据并保存以上是关于将普通对象投射到猫鼬文档的主要内容,如果未能解决你的问题,请参考以下文章