I'm learning to work in GAE. I'm so used to SQL, but transform my way of think the last 20 years to NoSQL is a little hard for me.
I have the next simple structure:
BOOKSthan can have
CHAPTERSthat can have
In a traditional SQL I just make foreign keys from
CHAPTERS, and from it to
I do this for my models in Datastore:
class Book(db.Model): title = db.StringProperty(required=True) author = db.StringProperty(required=True) created = db.DateTimeProperty(auto_now_add=True) # Get all the Chapters for a book def getChapters(self): key = self.chapterMemkey() chapters = memcache.get(key) if chapters is None: logging.info('DB access for key %s.', key) chapters = Chapter.all().ancestor(self).order("number").fetch(100) if not memcache.set(key, chapters, 300): logging.error('Memcache set failed for Chapters.') else: logging.info('Memcache for key %s.', key) return chapters class Chapter(db.Model): """ All chapters that a book have """ title = db.StringProperty(required=True) number = db.IntegerProperty(default=1) created = db.DateTimeProperty(auto_now_add=True) book = db.ReferenceProperty(Book, required=True, collection_name='chapters') # Search by Book (parent) @classmethod def byBook(cls, book, limit=100): chapter = book.getChapters() return chapter # Search by id @classmethod def byId(cls, id, book): return Chapter.get_by_id(long(id), parent=book) class Vote(db.Model): """ All votes that a book-chapter have """ chapterNumber = db.IntegerProperty(required=True) option = db.IntegerProperty(default=1) value = db.IntegerProperty(default=1) book = db.ReferenceProperty(Book, required=True, collection_name='book_votes') chapter = db.ReferenceProperty(Chapter, required=True, collection_name='chapter_votes') # -------------------------- # ClassMethods for the class # -------------------------- # Search by Book (parent) @classmethod def byBook(cls, book, limit=100): vote = book.getVotes() return vote # Search by id @classmethod def byId(cls, id, book): return Vote.get_by_id(long(id), parent=book)
Well, my doubts are:
- Is this approach correct?
- Must I define in the
Voteclass a reference for a book and for a chapter, as it was a foreign keys (just like I think I've done)?
- Is well defined the way to retrieve the chapters from a book? I mean, in the
Chapterclass the function
byBookuses a function from the
In the Vote class, I also define the
byBookfunction but, must I define another
byChapterfunction with similar behaviour than the
myBookfunction? I mean something like that:
@classmethod def byChapter(cls, chapter, limit=100): vote = chapter.getVotes() return vote
Are the parents well-defined for
Votes(book) or must
Chapterinstead be a
Book? The votes are for the chapters, but a chapter belongs to book.
Which are the right ways to get the sum of all the votes for a specific chapter and for specific book?