0

目前,对于使用 DataStore 的 AppEngine 应用程序,我有以下模型结构(为清楚起见而缩写):

class User(db.Model):
    name = db.StringProperty()
class Game(db.Model):
    name = db.StringProperty()
class UserGame(db.Model):
    user = db.ReferenceProperty(User)
    game = db.ReferenceProperty(Game)
    high_score = db.IntegerProperty()

游戏多,用户多。我正在尝试查询用户尚未加入的游戏列表,类似于(伪)SQL 等价于SELECT * from Game where name NOT IN (SELECT * from UserGame where user = <<current_user>>)

我的第一种方法是获取 UserGames 列表并遍历该列表,添加.filter('__key__ !=',<<user_key>>)但不可能链接不等式过滤器。

我的问题是,有没有更好的建模想法人们可以想象得到我需要的数据,或者我应该将所有内容迁移到 CloudSQL?我看不到如何使用我正在使用的当前模型在数据存储级别获取这些信息。

我知道我可以通过保留该用户的 UserGame 列表来以编程方式执行此操作,抓取 Game.all(),并以编程方式过滤掉结果,但这并不理想,因为我想使用光标对结果进行分页。

谢谢大家的帮助!

4

3 回答 3

1

您可以使用快速投影查询来获取用户的游戏密钥列表。当您拥有所有游戏密钥的列表时,您可以使用 Python 集来找到答案。要获取所有游戏键的列表,如果需要进一步优化,可以执行快速 key_only 查询并保存(pickle)此列表。

这是一个关于 appengine 的精彩视频:SQL 与 NoSQL:后端之战 https://developers.google.com/events/io/sessions/gooio2012/306/

于 2012-11-02T15:44:43.730 回答
0

如果您的游戏是固定的,则可能有一种“不同”的方式来做到这一点。具体来说,如果游戏没有及时更改,那么您可以User使用包含所有游戏的属性初始化模型,并且对于用户加入的每个游戏,将其从列表中删除。因此,您始终可以拥有未加入游戏的列表。

此外,为了避免大量的写入操作,您可以将此属性设置为未索引。

于 2012-11-02T20:51:47.427 回答
0

好的,我想通了。事实证明,您确实必须使用未记录的__key__属性来过滤您的查询。基本上,您使用 DataStore 来查询要首先过滤掉的实体,类似于以下内容:

joined_list = models.UserGame.all()
joined_list.filter('user =', <<current_user>>)

然后你遍历它并使用过滤掉!=,就像这样:

for joined in joined_list:
    games.filter('__key__ !=', joined.key())

这里唯一的问题是您不能在任何其他属性上使用不等式(DataStore 限制)。

这将为您提供用户尚未加入的所有游戏的列表。

希望这对其他人有帮助!

于 2012-11-03T18:19:11.737 回答