AppEngine过滤不等式与列表替代

时间:2012-11-02 14:45:53

标签: google-app-engine nosql google-cloud-datastore google-cloud-sql

目前,我使用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()

有很多游戏,并且有很多用户。我正在尝试查询用户尚未加入的游戏列表,类似于({1}}

的(伪)SQL等价物

我的第一个方法是获取UserGames列表并遍历该列表,添加SELECT * from Game where name NOT IN (SELECT * from UserGame where user = <<current_user>>),但不可能链接不等式过滤器。

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

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

感谢大家的帮助!

3 个答案:

答案 0 :(得分:1)

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

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

答案 1 :(得分:0)

如果您的游戏已修复,可能会有“不同”的方法。具体来说,如果游戏没有及时更改,那么您可以使用包含所有游戏的属性初始化User模型,并且对于用户加入的每个游戏,将其从列表中删除。因此,您可以随时获得未加入游戏的列表。

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

答案 2 :(得分: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限制)。

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

希望这可以帮助其他人!