Google app engine gql query two properties with same string
I have a data model开发者_高级运维 called Game
.
In the Game
model, I have two properties called player1
and player2
which are their names.
I want to find a player in game
but I don't know how to buil the query because gql does not support OR
clause and then I can't use select * from Game where player1 = 'tom' or player2 = 'tom'
statement.
So, how can I solve this question?
Do I have to modify my data model?With your current data model, you would need to do 2 queries, one for player1 and one for player2, and then merge the results in your local Python code.
Another option that would require a schema change would be to replace both fields with a single ListProperty, e.g.:
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')
This works because players can now be queried with a single index.
I would agree with Drew's answer as the way to go, but if you are stuck with your schema or just want to explore other options you could look at using Python sets to find the union of the two queries.
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) )
This example would use 3 RPC calls/queries but by only fetching the keys to perform the union you are making faster than usual queries. However depending on how many records you are filtering you might find it quicker without the keys only query and use a simpler check like
games1 = Game.all().filter("player1 =", name)
games2 = Game.all().filter("player2 =", name)
games = games1+filter(lambda x:x not in games1,games2)
Note that there is no gain of performance in using Drew's schema, because queries in list properties must check for equality against all the elements of the list.
精彩评论