I’m making a product review service using Google App Engine, and I’m wondering about good practice for structuring my datastore models (I’m using the “high replication” setting, and I’ve gathered that the way you structure entities and their ancestors is quite important). Particularly, I’m wondering about using lists of keys (or if I should be using ancestors/parents instead). My basic model looks like this:
-------------
- Product -
------------- ----------
- [reviews] - ----> - Review -
- - / ---------- -------------
------------- | - author - ---> - User -
| - - -------------
| ---------- - [reviews] - --|
| - - |
| ------------- |
| |
--------------------------------------
As you can see, each product contains a list of reviews, and each user account also contains a list of reviews written by the user. My main questions are about these lists of reviews and whether it’s best to store them as lists of review keys, or whether it’s better to just generate them on the fly using queries.
It seems that for the list of reviews related to a given product, the best thing to do might be to create the Review entities as children of the given Product, and then just create the list of reviews on-the-fly when I need it using an ancestor query, e.g.:
reviews = db.GqlQuery("SELECT * "
"FROM Review "
"WHERE ANCESTOR IS :1 "
"ORDER BY date DESC LIMIT 10",
product_key)
However, for getting a list of reviews written by a given user, I can’t think of a way to do the same as above. It seems I would have to store a list of keys that pertain to each review the user has written. Is this correct? If so, what’s the best way to store a list of keys in GAE datastore?
Any help or insight into this scenario as it relates to GAE datastore and/or general database design would be greatly appreciated. I’m pretty new to database design in general, so the more help the better. Thanks!
I would suggest doing neither – instead, use foreign keys. If the Review has a
db.ReferencePropertyto the product it’s for and the user who wrote it, you can easily fetch all the reviews for a product (Product.review_set.all()), all the reviews a user has written (User.review_set.all()), and the product and user for a review.