在 MongoDB 中存储和检索 JavaScript 对象

Posted

技术标签:

【中文标题】在 MongoDB 中存储和检索 JavaScript 对象【英文标题】:Storing and retrieving JavaScript objects in/from MongoDB 【发布时间】:2011-08-12 06:26:17 【问题描述】:

我目前正在使用 node-mongo-native 驱动程序使用 node.js 和 MongoDB。

我使用 Mongo 控制台存储和检索 JS 对象进行了一些测试。我发现,如果我存储一个包含函数/方法的对象,则方法和函数也将存储在集合中。这很有趣,因为我认为函数不能存储在 MongoDB 中(system.js 集合除外,正如Mongo docs 所建议的那样)。 此外,它不仅会存储方法,而且实际上会存储对象整个原型链的每个方法和成员。除此之外,我不喜欢这种行为,并认为它不直观,我不能拥有它。

我打算管理 Mongo 集合中的用户。为此,我有一个 User 对象,其中包含所有用户方法,用作每个用户实例的原型。用户对象本身只包含用户属性。

如果我将用户存储在 Mongo 集合中,我只想存储用户对象自己的属性。没有原型成员,尤其是没有原型方法。目前我看不到如何干净地做到这一点。我认为可能有效的选项是:

    使用 foreach 和 hasOwnProperty 创建一个浅拷贝,并将该拷贝存储在集合中。 为每个用户添加一个数据属性,该属性包含对象的所有属性并且可以存储在集合中。 我刚想到写这个:我还可以将所有原型属性设置为不可枚举,应该阻止它们存储在集合中。

但是,反过来我也有同样的问题:从集合中加载用户时。 AFAIK 在创建对象原型后无法更改 javascript 中的对象原型。当 Mongo 实例化从集合中检索到的对象时,也无法指定要使用的原型。所以基本上我总是使用 Mongo 获取从 Object 继承的对象。据我所知,从此时起,我有 2 个选项可以恢复可用的用户对象:

    创建一个继承自 User 的新对象,并将结果对象的每个属性复制到新创建的对象。 (兼容存储机制 1 和 3) 创建一个继承自 User 的新对象,并将结果对象作为数据属性存储在新创建的对象上。 (兼容存储机制2)

我的假设是否正确,尤其是关于为查询结果指定原型的可能性?什么是正确的方法,为什么?我肯定不是第一个使用 node.js 在 MongoDB 中存储和恢复对象的人。

目前我会采用 2/2 的方法。我不是很喜欢它,但它是最有效的,也是唯一一个与 API 一起干净地工作的。但是,我更愿意听到 API 实际上并没有做错什么,但我这样做是因为不知道如何正确使用它。所以请赐教:)

【问题讨论】:

【参考方案1】:

我最近才意识到,实际上可以在 V8/node 中更改对象原型。虽然这不在标准中,但在各种浏览器中是可能的,尤其是在 V8/node 中!

function User(username, email) 
    this.username = username;
    this.email = email;


User.prototype.sendMail = function (subject, text) 
    mailer.send(this.email, subject, text);
;

var o = username: 'LoadeFromMongoDB', email: 'nomail@nomail.no';
o.__proto__ = User.prototype;
o.sendMail('Hello, MongoDB User!', 'You where loaded from MongoDB, but inherit from User nevertheless! Congratulations!');

这被用于各种模块和插件——即使是核心模块也使用这种技术,尽管它不是 ECMAScript 标准。所以我想在 node.js 中使用是安全的。

【讨论】:

我很高兴读到您能够在 mongodb 中使用 JS 函数存储对象(使用 mongodb-native 驱动程序?),但似乎驱动程序跳过了对象方法并且只存储属性对我来说可接受的类型(字符串、数字、数组、对象等)。你做了什么特别的事吗?还是我看错了你的问题? 您不能将这些方法存储在 MongoDB 中。我正在做的是将 Mongo 驱动程序返回的 JS 对象上的原型替换为我想要的任何内容。这将允许它调用原型上存在的方法,就好像它们存在于驱动程序返回的对象上一样。如果您无法理解这一点,您应该阅读原型继承在 JS 中的工作原理。 好的,感谢您的澄清,因为这部分极具误导性:“我发现,如果我存储一个包含 functinos/methods 的对象,则方法和函数也将存储在集合中。这是很有趣,因为我认为函数不能存储在 MongoDB 中(除了 system.js 集合,正如 Mongo 文档所建议的那样)。” -- 所以是的,函数不能存储在 MongoDB 中。【参考方案2】:

我不确定我是否完全在关注你的问题......但我想到了一件事:你检查过 Mongoose ORM 吗? (http://mongoosejs.com/)

在定义模型和方法时,它为您提供了很多选择。特别是“虚拟”可能会引起人们的兴趣 (http://mongoosejs.com/docs/virtuals.html)。

不管怎样,希望对大家有所帮助!

【讨论】:

我知道猫鼬。但我不喜欢它。我一直在寻找的是使用 Mongo 和 JavaScript 处理对象属性存储的某种“最佳实践”。不是另一个图书馆。不过还是谢谢你的回答!

以上是关于在 MongoDB 中存储和检索 JavaScript 对象的主要内容,如果未能解决你的问题,请参考以下文章

MongoDB:存储的base64缓冲区数据和检索的base64不匹配

在容器上运行的 mongoDB 中创建集合和检索数据的方法

mongodb Gridfs操作

在 Spring MongoDB 存储库中使用 $slice 和 @Query

检索存储在我的 Mlab 中的音频 - 二进制文件

MongoDB 数据自动同步到 ElasticSearch