如何重命名 Datastore 实体字段但能够通过新旧 属性 名称检索记录?

How to rename a Datastore entity field but be able to retrieve records via old and new property names?

我有一个实体

class Foo {
  public String bar;
}

我想将 "bar" 重命名为 "somethingElse"。并计划使用 Objectify 的 @AlsoLoad 注释来实现这一点(我已经在使用 Objectify 来实现持久性)。所以像:

class Foo {
  @AlsoLoad("bar")
  public String somethingElse;
}

但是任何形式的查询:

final Query<Foo> query = OfyService.ofy().load().type(Foo.class)
    .filter("somethingElse", "someValue");

只检索重命名后保存的实体。任何较旧的实体都将被忽略。

重命名实体字段的最佳做法是什么,以便我可以有一个查询 return 所有记录?

注意:我不是 objectify 用户,答案是通用的,因此您必须对其进行调整以适应 objectify 细节。

一般来说,您希望避免长时间同时使用 barsomethingElse,这主要是因为查找匹配实体会转化为 OR 类型的查询 - .filter("bar", "someValue") OR .filter("somethingElse", "someValue"),数据存储根本不支持。来自 Restrictions on queries:

The NOT, OR, and != operators are not natively supported, but some client libraries may add support on top of Cloud Datastore.

这意味着,充其量,您必须克服重重困难才能完成这样的工作,例如,参见

我的建议是执行一次性迁移并完成它。它将包含以下步骤:

  • 很可能在迁移过程中您需要两个属性configured/alive,所以不要只是重命名bar,而是添加somethingElse 并且不要立即删除 bar
  • 在您更新 bar 属性 的所有地方也相应地更新 somethingElse
  • 添加逻辑以查询所有具有 bar 但不具有 somethingElse 的实体并重新编写它们,使它们也具有 somethingElse。完成此步骤后,所有实体都应具有 somethingElse 镜像 bar
  • 在您读取 bar 值的所有非查询位置切换为读取 somethingElse 而不是
  • 检查所有包含 somethingElse 的索引是否都在服务,然后将您的查询从 bar 切换到 somethingElse。这样实际迁移就完成了,您可以执行下面的清理步骤
  • 放弃写入 bar 属性
  • 对具有 bar 属性 的所有实体执行查询,并在没有 bar 的情况下重写它们。请注意,这可能比实际留下这些实体更昂贵
  • 从您的模型和索引中删除 bar(如果适用于您的客户端库),但前提是您在上一步中从所有实体中删除了 属性

按照这种方法进行的迁移可以执行得很慢,因为它不需要完全关闭服务,可以 live.