问题描述
我有一个实体
class Foo {
public String bar;
}
我想将bar重命名为somethingElse。并计划使用Objectify的@AlsoLoad注解来实现这一点(我已经在使用Objectify进行持久化)。例如:
class Foo {
@AlsoLoad(bar)
public String somethingElse;
}
但是任何形式的查询:
最终查询< Foo> query = OfyService.ofy()。load()。type(Foo.class)
.filter(somethingElse,someValue);
仅检索自重命名后已保存的实体。任何较旧的实体都会被忽略。
重命名实体字段的最佳做法是什么,以便我可以有一个将返回所有记录的查询?
$ b $注意:我不是一个客观化的用户,答案是通用的,所以你必须适应它来物化具体细节。 b$ b
一般而言,您希望避免在长期使用栏
和 somethingElse
主要是因为找到匹配的实体转换为或
类型的查询 - .filter(bar,someValue)
或 .filter(somethingElse,someValue)
,这从根本上不受数据存储的支持。从:
这意味着,最好的情况是,你必须跳过这些环节才能做出类似这样的工作,例如,请参阅
我的建议是执行一次性迁移并完成它。它将包含以下步骤:
- 您很可能必须在配置/活动期间 迁移,所以不要只重命名
bar
,而应该添加somethingElse
并且不要立即删除<$ c $在您更新栏
属性的所有地方,您都可以更新 - > somethingElse 据此添加逻辑来查询所有具有
bar
但没有somethingElse
并重新编写它们,使它们也具有somethingElse
。完成此步骤后,所有实体都应具有somethingElse
镜像bar
- 在您阅读
bar
的值的所有非查询位置切换到阅读somethingElse
而不是
- 检查包含
somethingElse
的所有索引是否在服务,然后将您的查询从bar
切换到somethingElse
。有了这个,实际的迁移就完成了,您可以执行下面的清理步骤
- 放置
栏
属性
- 为所有具有
bar
属性的实体执行查询,并在没有bar
的情况下重新编写它们。请注意,这可能比实际上将这些实体单独留在您的模型和索引(如果适用于您的客户端)更加昂贵
- drop
bar
库),但仅当您在上一步骤中从所有实体中删除属性时
- 检查包含
使用此方法的迁移可以缓慢执行因为它不需要完整的服务关闭,所以可以直播。
I have an entity
class Foo {
public String bar;
}
I want to rename "bar" to "somethingElse". And was planning on using Objectify's @AlsoLoad annotation to achieve that (I am already using Objectify for persistence). So something like:
class Foo {
@AlsoLoad("bar")
public String somethingElse;
}
But any queries of the form:
final Query<Foo> query = OfyService.ofy().load().type(Foo.class)
.filter("somethingElse", "someValue");
Only retrieve entities that have been saved since the rename. Any older entities are ignored.
What is best practice for renaming entity fields so that I can have a single query that will return all records?
Note: I'm not an objectify user, the answer is generic, so you'd have to adapt it to objectify specifics.
In general you want to avoid using both bar
and somethingElse
for extended periods of time, primarily because finding matching entities translates into an OR
type of query - .filter("bar", "someValue")
OR .filter("somethingElse", "someValue")
, which is fundamentally unsupported by the datastore. From Restrictions on queries:
This means that, at best, you'd have to jump through hoops to make something like this work, see, for example, Google Datastore combine (union) multiple sets of entity results to achieve OR condition
My suggestion is to perform a one-off migration and be done with it. It would contain the following steps:
- most likely you'll have to have both properties configured/alive during the migration, so don't just rename
bar
, instead addsomethingElse
and don't immediately deletebar
- in all places where you update the
bar
property also updatesomethingElse
accordingly - add logic to query for all entities which have
bar
but don't havesomethingElse
and re-write them so they also havesomethingElse
. After this step completes all the entities should have asomethingElse
mirroringbar
- in all non-query places where you read
bar
's value switch to readingsomethingElse
instead - check that all indexes containing
somethingElse
are serving, then switch your queries frombar
tosomethingElse
. With this the actual migration is complete and you can execute the cleanup steps below - drop writing the
bar
property - perform queries for all entitites having a
bar
property and re-write them withoutbar
. Note that this could be more expensive than actually leaving these entities alone - drop
bar
from your models and indexes (if applicable to your client library), but only if you deleted the property from all your entities in the previous step
A migration following this approach can be performed slowly as it doesn't require complete service shutdown, it can be done live.
这篇关于如何重命名数据存储实体字段,但能够通过旧的和新的属性名称检索记录?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!