- mongodb - 在 MongoDB mapreduce 中,如何展平值对象?
- javascript - 对象传播与 Object.assign
- html - 输入类型 ="submit"Vs 按钮标签它们可以互换吗?
- sql - 使用 MongoDB 而不是 MS SQL Server 的优缺点
所以我有一个需要存储某些配置信息的应用程序,因此我计划将配置存储为 Mongo 中的简单 JSON 文档:
appConfig: {
fizz: true,
buzz: 34
}
这可能会映射到 Java POJO/实体,例如:
public class AppConfig {
private boolean fizz;
private int buzz;
}
等等。通常,对于关系数据库,我使用 Hibernate/JPA 进行从表数据到 Java 实体的 O/R 映射。我相信最接近 table/Hibernate 的 JSON/Mongo 伴侣是 Morphia/GSON 组合:使用 Morphia 驱动从我的 Java 应用程序到 Mongo 的连接,然后使用 GSON 到 O/J 将 JSON 映射到/来自 Java POJO/实体。
这里的问题是,随着时间的推移,我的 appConfig
文档结构会发生变化。可能很简单,例如:
appConfig: {
fizz: true,
buzz: 34
foo: "Hello!"
}
这需要 POJO/实体变成:
public class AppConfig {
private boolean fizz;
private int buzz;
private String foo;
}
但问题是我可能有数以万计的 JSON 文档已经存储在 Mongo 中,其中没有 foo
属性。在这种特定情况下,显而易见的解决方案是在属性上设置一个默认值,例如:
public class AppConfig {
private boolean fizz;
private int buzz;
private String foo = "Hello!"
}
但实际上,AppConfig
文档/模式/结构最终可能会发生如此大的变化,以至于它在任何方面、形状或形式都不像其原始设计。但关键是:我需要向后兼容,并且最好能够更新/转换文档以在适当的情况下匹配新的架构/结构。
我的问题:这个“版本化文档”问题通常是如何解决的?
最佳答案
我通常通过为集合中的每个文档添加一个版本字段来解决这个问题。
AppConfig 集合中可能有多个文档:
{
_id: 1,
fizz: true,
buzz: 34
}
{
_id: 2,
version: 1,
fizz: false,
buzz: 36,
foo: "Hello!"
}
{
_id: 3,
version: 1,
fizz: true,
buzz: 42,
foo: "Goodbye"
}
在上面的示例中,版本 1 有两个文档,版本 0 有一个旧文档(在此模式中,我通常将缺失或空版本字段解释为版本 0,因为我总是只添加一次'm 通过生产中的文档进行版本控制)。
这种模式的两个原则:
您可以通过检查版本字段并在版本不够新时执行迁移来做到这一点:
DBObject update(DBObject document) {
if (document.getInt("version", 0) < 1) {
document.put("foo", "Hello!"); //add default value for foo
document.put("version", 1);
}
return document;
}
此迁移可以相当轻松地添加具有默认值的字段、重命名字段和删除字段。由于它位于应用程序代码中,因此您可以根据需要进行更复杂的计算。
文档迁移后,您可以通过任何您喜欢的 ODM 解决方案运行它,将其转换为 Java 对象。该解决方案不再需要担心版本控制,因为它处理的文档都是最新的!
对于 Morphia,这可以使用 @PreLoad 来完成。注释。
两个警告:
有时您可能希望立即将升级后的文档保存回数据库。最常见的原因是迁移成本高昂、迁移不确定或与其他数据库集成,或者您急于升级旧版本。
添加或重命名用作查询条件的字段有点棘手。在实践中,您可能需要执行多个查询,并统一结果。
在我看来,这种模式突出了 MongoDB 的一大优势:由于文档在应用程序中进行了版本控制,因此您可以在应用程序中无缝迁移数据表示,而无需像使用 SQL 那样需要任何离线“迁移阶段”数据库。
关于java - 与 Mongo 的版本化对象/JSON 映射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24521718/
无法使用 Hive 版本 1.1.0 HBase 版本 0.94.8 和 hadoop 版本 2.7.0 从 hive 创建 Hbase 表 hive (default)> CREATE TABLE
我试图为 electron app 创建可执行文件但面临这个问题 Unable to determine Electron version. Please specify an Electron ve
我正在尝试让自适应阈值在 python 绑定(bind)到 opencv 中工作(swig 一个 - 无法让 opencv 2.0 工作,因为我正在使用 beagleboard 因为交叉编译还没有工作
我一直在 linux 机器上使用 JMeter,在命令行下使用了一段时间。工作正常。 今天,我在 Windows 机器(新客户端等)上尝试了它,它确实可以工作,但在控制台窗口中输出有很大不同。 Lin
在我的编码环境中,我通常使用最新版本的 Java 和 Eclipse。当我编写源代码时,我不会注意我使用的 API 方法或类是否向后兼容旧版本的 Java 或 Eclipse。在 javadoc 中存
问题是关于版本的特定组合,但更普遍。 我刚刚从 Kubuntu 12.04 升级到 14.04。现在,当我想编译 CUDA 代码(使用 CUDA 6.5)时,我得到: #error -- unsupp
我目前正在对我的一些应用程序进行沙箱处理,看来我必须删除一些功能才能满足 Mac App Store 沙箱(和其他)规则。 显然用户不会因为失去功能而感到高兴,我担心他们不会指责苹果制定了愚蠢的规则,
我用 flash 和 js 版本创建了一个动画横幅。 是否可以检测低于版本 9 的 ie 版本,然后提供 Flash 横幅,否则提供 js 横幅。 最佳答案 您可以使用条件注释来检测 IE 版本
我有一个处理不同位置的数据库的应用程序,我想检查这些数据库是否使用 Firebird 2.5 或更高版本打开。我们最近从 Firebird 2.0 迁移到了 2.5,我们有很多数据库可以响应 sele
我正在开发一个应用程序,我使用托管在我的服务器上的 Java 和 Jersey 构建了后端部分。我在服务器上使用 Tomcat7 来调用 Web 服务。 我以前有一台安装了 Ubuntu 的计算机,我
我可以使用 GetVersionEx() 函数来获取 Windows 版本,但是这个函数将返回一个数字而不是一个字符串。但是没有问题,因为我可以将数字转换为字符串,例如: if (osvi.dwMaj
我已经在我的系统中安装了 Anaconda 2 & 3。 Anaconda 2 包含 python 2.7 & Anaconda 3 包含 python 3.6。 我需要使用命令提示符运行我的 pyt
我正在尝试构建一个 Android 项目,但发生了以下错误 Error:(10, 1) A problem occurred evaluating project ':app'. > Failed t
关闭。这个问题需要更多focused .它目前不接受答案。 想改进这个问题吗? 更新问题,使其只关注一个问题 editing this post . 关闭 4 年前。 Improve this qu
在降级我的 GCC 之前,我想知道是否有办法确定我的机器中的哪些程序/框架或依赖项会中断,以及是否有更好的方法来执行 openpose 安装? (例如,在 CMake 中更改某些内容) 有没有办法在不
我已经在终端的代码sudo apt-get install Shadowsocks-qt5中安装了Shadowsocks-Qt5,然后我可以通过搜索找到启动图标,但是它当我点击图标时打不开。然后我尝试
在网络上找到的文档说,MLLP V2(第 2 版)是用于传输 HL7 版本 3 内容的所有消息传输协议(protocol)的要求。似乎 MLLP 第 2 版主要用于 HL7 第 3 版。 我们可以/应
我正在使用带有 selinium webdriver 的 Protractor 。我的chromeDriver版本是78.0.1,chrome版本是78.0.3904.97。两个版本都匹配,应该不会有
我正在按照教程设置 mysql 数据库并做一些事情。我无法找到数据库资源管理器。我读了很多,但在 Window->show View-> Dataxxx 或右侧上部选项卡中无法正常工作。 最佳答案 从
我已经在 KDE 桌面上安装了 Anaconda 2.0.1。当我运行 python 并看到所有已安装的模块时,我收到此消息“无法将不兼容的 Qt 库(版本 0x40801)与该库(版本 0x4080
我是一名优秀的程序员,十分优秀!