Google app引擎gql查询两个属性相同的字符串

时间:2011-05-03 21:24:09

标签: python google-app-engine

我有一个名为Game的数据模型。

Game模型中,我有两个名为player1player2的属性。

我想在game中找到一个播放器,但我不知道如何构建查询,因为gql不支持OR子句然后我不能使用select * from Game where player1 = 'tom' or player2 = 'tom'语句

那么,我该如何解决这个问题呢? 我是否必须修改我的数据模型?

3 个答案:

答案 0 :(得分:6)

使用您当前的数据模型,您需要进行2次查询,一次针对player1,另一次针对player2,然后将结果合并到本地Python代码中。

另一个需要更改架构的选项是用一个ListProperty替换两个字段,例如:

class Game(db.Model):
  players = db.ListProperty()

game1.players = ['tom', 'bob']
game2.players = ['joe', 'tom']

# this query will match all games where tom is one of the players
query = Game.all().filter('players =', 'tom')

这是有效的,因为现在可以使用单个索引查询玩家。

答案 1 :(得分:1)

我同意Drew的答案作为前进的方法,但如果您坚持使用您的架构或者只是想探索其他选项,您可以使用Python sets来查找两个查询的并集。

name = "The Player"
keys1 = set(Game.all(keys_only=True).filter("player1 =", name))
keys2 = set(Game.all(keys_only=True).filter("player2 =", name))
games = Game.get( list(keys1 | keys2) )

此示例将使用3个RPC调用/查询,但仅通过获取键来执行联合,您比正常查询更快。但是,根据您过滤的记录数量,您可以更快地找到它,而无需仅使用密钥查询并使用更简单的检查,如

games1 = Game.all().filter("player1 =", name)
games2 = Game.all().filter("player2 =", name)
games = games1+filter(lambda x:x not in games1,games2)

答案 2 :(得分:0)

请注意,使用Drew的架构没有性能提升,因为列表属性中的查询必须检查列表中所有元素的相等性。