如何重命名数据存储区实体字段,但能够通过旧的和新的属性名称检索记录?

时间:2017-12-03 06:19:19

标签: google-app-engine google-cloud-datastore objectify

我有一个实体

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");

仅检索自重命名后已保存的实体。任何较旧的实体都会被忽略。

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

1 个答案:

答案 0 :(得分:4)

注意:我不是一个客观化的用户,答案是通用的,所以你必须使其适应客观化的细节。

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

  

本机不支持NOTOR!=运算符,   但是一些客户端库可能会在Cloud Datastore之上添加支持。

这意味着,最好的情况是,你必须通过箍来制作类似这样的作品,例如,参见Google Datastore combine (union) multiple sets of entity results to achieve OR condition

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

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

遵循此方法的迁移可以缓慢执行,因为它不需要完全关闭服务,可以 live 完成。