Google App Engine GQL 查询两个相同字符串属性
我有一个数据模型叫做 Game
。
在这个 Game
模型里,我有两个属性,分别叫 player1
和 player2
,它们是玩家的名字。
我想在 game
中找到一个玩家,但我不知道该怎么写查询,因为 gql 不支持 OR
条件,所以我不能用 select * from Game where player1 = 'tom' or player2 = 'tom'
这样的语句。
那么,我该怎么解决这个问题呢?
我需要修改我的数据模型吗?
3 个回答
0
请注意,使用Drew的方案并不会提高性能,因为在处理列表属性时,查询必须检查列表中所有元素是否相等。
1
我同意Drew的回答是个不错的选择,但如果你在数据库结构上遇到困难,或者想尝试其他方法,可以考虑使用Python中的集合来找出两个查询的并集。
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)
6
根据你现在的数据模型,你需要进行两次查询,一次是针对玩家1,另一次是针对玩家2,然后在你本地的Python代码中把结果合并起来。
还有一种选择是需要改变数据结构的,那就是把这两个字段替换成一个单独的列表属性,比如:
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')
这样做的好处是,现在可以通过一个索引来查询玩家。