且构网

分享程序员开发的那些事...
且构网 - 分享程序员编程开发的那些事

在NDB中使用密钥来检索实体

更新时间:2023-02-13 12:36:59

您可以通过做一个祖先查询而不是get:

  chapter_key = ndb.Key('Book',long(bookId),'Chapter',long chapterId))
page = Page.query(Page.pageNumber == pageNumber,ancestor = chapter_key)


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?

You can do this in one go by doing an ancestor query, rather than a get:

chapter_key = ndb.Key('Book', long(bookId), 'Chapter', long(chapterId))
page = Page.query(Page.pageNumber==pageNumber, ancestor=chapter_key)