Hi Nick,
On Jun 11, 4:19 am, "Nick Johnson (Google)" <
nick.john...@google.com>
wrote:
> Hi n8gray,
>
> Excellent question!
>
> Given the amount of information you're likely to store against Players2Games
> (GamePlayers, perhaps?), and the number of games any one player may have,
> and the likely access patterns, I would suggest sticking with a separate
> model for it.
Interesting -- I came to the opposite conclusion but maybe my
reasoning isn't sound. Here's what I've got right now (untested, so
it may contain syntax errors and such):
class GameState(VersionedModel):
# Parent should be a GameMeta
scores = db.ListProperty(int)
other gritty details of the current game state
class GameTurn(VersionedModel):
# Parent should be a GameMeta
creationDate = db.DateTimeProperty(auto_now_add=True)
player = db.ReferenceProperty(User)
turn_score = db.IntegerProperty()
more gritty details about this turn
This is the stuff you only care about if you're currently playing the
game. The scores may be better placed in GameMeta -- I haven't
decided yet.
class GameMeta(VersionedModel):
name = db.StringProperty(required=True)
password = db.StringProperty(indexed=False)
creationDate = db.DateTimeProperty(auto_now_add=True)
isActive = db.BooleanProperty(default=True)
# In case of tie, there can be more than one winner
winners = db.ListProperty(db.Key, default=None)
playerCount = db.IntegerProperty(required=True)
currentPlayer = db.ReferenceProperty(User, required=True)
currentPlayerNumber = db.IntegerProperty(default=0)
gameState = db.ReferenceProperty(GameState)
players = db.ListProperty(db.Key)
GameMeta holds all the metadata of the game. I moved the players list
in here (despite watching Brett Slatkin's I/O talk on list properties)
because I reasoned that a) the serialization/deserialization overhead
for 4 elements wouldn't be too bad, and b) You're going to want the
player list every time you retrieve the game anyway. If you think
this is unwise, however, I'm interested to hear why.
> The main lesson for using the datastore instead of a relational database is
> simply to denormalize and precalculate. In this case, that likely means
> storing running totals (number of turns, score, etc) against the
> Players2Games entity, instead of calculating them when needed as you might
> in a relational database.
Yeah, I was planning to do a fair bit of denormalization.
> Tony's point about entity groups is an excellent one. Based on the sort of
> updates you're likely to want to do, and the access patterns in an app like
> this, I would suggest making the Players2Games entities child entities of
> the related Games entity, and making the Turns entities likewise child
> entities of their Games entity. This way, each game has its own entity
> group, so you can make atomic (transactional) updates across the whole game
> with ease.
At least I got that part right!
Thanks,
-n8