Defining book models in GAE 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:


BOOKS than can have CHAPTERS
CHAPTERS that can have VOTES


In a traditional SQL I just make foreign keys from VOTES to CHAPTERS, and from it to BOOKS.

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 Vote class 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 Chapter class the function byBook uses a function from the Book class.
In the Vote class, I also define the byBook function but, must I define another byChapter function with similar behaviour than the myBook function? 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 Chapter instead 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?
This depends on a few things (keep reading).
Not necessarily. This is a question of optimization. You could fetch a vote's book by using Chapter as an intermediary (vote.getChapter().getBook()), but this would obviously require sequential trips to the database - one to get the vote, followed by one to get the chapter, and finally one to get the book. Do you plan on fetching a book for a vote frequently? If so, save some resources and stick with what you've got.
From a dependency standpoint, this seems counterintuitive, but since a chapter cannot exist without a book (can it?), I would say this is fine and simply a matter of preference. This always seems awkward to me as well, so maybe someone else can provide more info.
You can, again, this is a question of optimization and convenience. When you have questions like this, ask yourself, "will I really need this?". If the answer is no, or you're unsure, leave it out; you can always add it later if your needs change (the relations are setup correctly to do the joins, right?).
See above.
I would provide a Chapter.getVotesSum() and/or Book.getVotesSum(). These methods would include GQL queries to aggregate the appropriate rows from the votes table into a sum.


(Sorry if I'm missing something, I don't use GAE)