I have this structure: Books that have Chapters (ancestor=Book) that have Pages (ancestor=Chapter)
It is clear for me that, to search for a Chapter by ID, I need the book to search by ancestor query. And I've learn today that if I have all the keys, I can retrieve directly the entity without need of get first the book, then the chapter and then the page, in this way:
page_key = ndb.Key('Book', long(bookId), 'Chapter', long(chapterId), 'Page', long(pageId))
page = page_key.get()
My doubt is: to get the page by, for example, page number, must I get first the chapter?
For example :
class Book(ndb.Model):
name = ndb.StringProperty(required=True)
# Search by id
@classmethod
def by_id(cls, id):
return Book.get_by_id(long(id))
class Chapter(ndb.Model):
name = ndb.StringProperty(required=True)
# Search by id
@classmethod
def by_id(cls, id, book):
return Chapter.get_by_id(long(id), parent=book.key)
class Page(ndb.Model):
pageNumber = ndb.IntegerProperty(default=1)
content = ndb.StringProperty(required=True)
# Search by page
@classmethod
def by_page(cls, number, chapter):
page = Page.query(ancestor=chapter.key)
page = page.filter(Page.pageNumber == int(number))
return page.get()
Actually, when I need to search the Page to display its contents, I'm doing this:
getPage?bookId=5901353784180736&chapterId=5655612935372800&page=2
So, in the controller, I make this:
def get(self):
# Get the id parameters
bookId = self.request.get('bookId')
chapterId = self.request.get('chapterId')
pageNumber = self.request.get('page')
if bookId and chapterId and pageNumber:
# Must be a digit
if bookId.isdigit() and chapterId.isdigit() and pageNumber.isdigit():
# Get the chapter
chapter_key = ndb.Key('Book', long(bookId), 'Chapter', long(chapterId))
chapter = chapter_key.get()
if chapter:
# Get the page
page = Page.by_number(pageNumber, chapter)
Is this the right way or there is a better way I'm missing where I can do only an access to datastore, instead two?
If this is right, I suppose that this way of work, using NDB, does not have any impact on the datastore, because repeated calls to this page always hit the NDB cache for the same chapter and page (because I'm using get() method, it is not a fetch() command). Is my suppose right?