Java 如何在MongoDB/Morphia中处理查询迁移?

Java 如何在MongoDB/Morphia中处理查询迁移?,java,mongodb,migration,database-migration,morphia,Java,Mongodb,Migration,Database Migration,Morphia,最近,我不得不对“用户”集合的数据结构进行更改,这导致从以下简化示例迁移: { "name": "John", "emails" : [ "a@a.a", "b@b.b" ] } 为此: { "name": "John", "emailAddresses" : [ { "email" : "a@a.a", "verified" : true }, { "email"

最近,我不得不对“用户”集合的数据结构进行更改,这导致从以下简化示例迁移:

{ 
   "name": "John",
   "emails" : [ "a@a.a", "b@b.b" ]
}
为此:

{ 
   "name": "John",
   "emailAddresses" : [ 
       { 
         "email" : "a@a.a",
         "verified" : true
       },
       { 
         "email" : "b@b.b",
         "verified" : true
       }
    ]
}
因此“emails”字段从一个简单的字符串数组更改为一个复杂对象数组,每个对象都有一个字段“email”和“verified”。除此之外,它的名称改为“电子邮件地址”

我知道如何使用Morphia提供的注释(如
@PostLoad
@NotSaved
)迁移有关加载和存储已更改数据模型的数据

我的问题出在疑问上。最初,我会按用户的电子邮件地址进行查询,如下所示:

Query<User> q = dataStore.createQuery(User.class);
q.filter("emails", email);
User u = q.get();
Query q=dataStore.createQuery(User.class);
q、 过滤(“电子邮件”,电子邮件);
用户u=q.get();
我知道我只需将查询调整为以下内容,以支持我的新数据结构:

Query<User> q = dataStore.createQuery(User.class);
q.filter("emailAddresses.email", email);
User u = q.get();
Query q=dataStore.createQuery(User.class);
q、 过滤器(“emailAddresses.email”,电子邮件);
用户u=q.get();
那很好。问题是,我收藏的一些文档仍然以“旧”的方式存储,有些文档已经以“新”的方式存储。如果我只使用“新”方式,我将无法找到旧文档

问题是:

如何创建同时考虑新旧数据的查询 当(如本例中)按电子邮件地址查询时的结构

到目前为止,我能想到的最好的办法是使用“或”查询,并在禁用验证的情况下对这两个字段进行查询(否则会引发异常):

Query q=dataStore.createQuery(User.class);
q、 禁用验证();
q、 或(q.criteria(“电子邮件”).equal(电子邮件),q.criteria(“emailAddresses.email”).equal(电子邮件));
用户u=q.get();
然而,这似乎相当麻烦,并且可能对性能有害。 我想知道是否有更好的方法来解决这个问题


您不必只使用Morphia注释。可以使用MongoDB命令行运行更新查询。您可以使用JavaScript执行相当复杂的逻辑来查找文档并将其转换为新格式。如果在旧的“电子邮件”字段上有索引,并且有数百万个文档,那么您只能在这些文档上运行它

为什么不将旧文档更新为新格式?这将如何进行?我有一个实时运行的服务器,当前使用旧的查询,还有一个数据库使用旧的数据结构。如果我将服务器更新为仅使用新查询,则查询将失败,直到运行更新脚本。另一方面,如果我先更新数据库,然后更新服务器,查询也会在短时间内失败。有没有办法做到这一点而不停机或中断?很公平。问题中没有提到0停机时间。不,没有,我的错。你的建议很好,但是考虑到“零停机”因素,你会怎么做呢?如果没有停机,我想除了一些繁琐而缓慢的查询,别无选择。我以前也这样做过,然后运行一些升级代码(迭代所有实体并更改它们的结构-不确定是否可以使用标志自动完成),一旦所有内容都迁移到新结构。您可能希望在流量较少的情况下执行此操作。感谢您的回复,我最终编写了自己的更新脚本,该脚本以当前和新服务器都可以处理的方式转换了现有数据。升级到新的服务器版本后,我运行了另一个“清理”脚本来清除冗余数据。
Query<User> q = dataStore.createQuery(User.class);
q.disableValidation();
q.or(q.criteria("emails").equal(email), q.criteria("emailAddresses.email").equal(email)); 
User u = q.get();