2012-07-06 35 views
7

我需要做一个Transaction内的查询,但我不知道实体@Id,我有什么是一个字段的值,如用户名,但不是ID,交易中只允许祖先查询,如何处理?

所以,换句话说,我无法创建Key来执行查询。我如何做一个查询来获得Transaction内的实体?

+1

如你所知,你不能那样做。这似乎是一个设计问题。也许你可以尝试通过你想要做的事来问这个问题。 – sahid 2012-07-06 15:03:03

回答

14

没有钻研更深层次的设计问题,实际上有两种选择:

1)执行事务之外的查询。对象化(你用这个标签标记了这个帖子)使得即使在事务内部执行非事务性查询也很容易。只需创建一个新的与事务无关的实例并使用它来运行查询......然后返回到您的事务中工作。请记住,这确实会突破交易并可能影响操作的完整性。通常它并不重要。

如果您使用Objectify4你可以运行这样的操作:

ofy.transactionless.load().type(Thing.class).filter("field", value)...etc 

2)使用查找实体

这个事情例如用户名打交道时通常是正确的答案。创建该用户名映射到用户对象这样一个独立的实体:

class Username { 
    @Id String username; 
    Key<User> user; 
} 

使用XG交易创建一个用户名每次创建一个用户的时间,并更新它,如果你让你的用户名更改。现在,要通过用户名执行用户的交易查询,请首先查找用户名,然后使用它查找用户。

+0

我想使用字符串ID,我可以为它的用户名ID然而,hwen我有一个字符串ID是一个随机字符串,也许可以从短字符串到很长的字符串范围。我可以看到Datastore Key是“膨胀”,我的意思是GAE Key与@Id的长度成正比,我该如何处理? – xybrek 2012-07-06 15:46:27

+0

这听起来像是不成熟的优化。除非您计划存储PB字节,否则我不会担心这一点。 – stickfigure 2012-07-07 06:13:34

+0

正确,但是这不会降低性能,读/写需要花费更长的时间才能提交?如果没有,我很好。然而,我担心我的应用程序将被计为计算时间。如此长的读/写意味着更昂贵? – xybrek 2012-07-07 06:30:09

0

我有类似的问题,我想出的最简单的方法是使用一个虚拟父实体。除了使用XG事务并为每个其他用户实体插入另一个用户实体外,只需创建一个虚拟父实体并将其设置为从此处创建的每个用户实体的祖先。我认为这种方法可以节省大量的空间和数据管理问题。

+2

这样做的缺点是所有的用户实体最终都在一个实体组中,根据文档,每个seipry组只能写一个:[Datastore documentation](https://cloud.google.com/ appengine/docs/python/datastore/structuring_for_strong_consistency?csw = 1) – 2014-12-13 18:42:54

+0

我不知道这个限制。感谢您指出。 – kerafill 2014-12-16 21:47:48