2013-05-21 52 views
2

我正在學GAE工作。我已經閱讀了很多論文,Google的所有NDB文檔以及這裏的一些問題。我非常習慣SQL,但是我認爲過去20年來NoSQL對我來說有點困難,所有這些不同的解決方案都給了我這裏,讓我發瘋。GAE:從RDBMS到NDB問題

我有下一個簡單的結構: 書比可以具有章和 章和可以具有票數 例如,書「前哨」可以有3個章節,每章將具有各自爲0,圖8和12票。

在傳統的SQL中,我只是從VOTES到章節和書籍以及從章節到書籍的外鍵。

我這樣做對我的模型:

class Book(ndb.Model): 
    title = ndb.StringProperty(required=True) 
    author = ndb.StringProperty(required=True) 
    created = ndb.DateTimeProperty(auto_now_add=True) 

    # Define a default ancestor for all the books 
    @staticmethod 
    def bookKey(group='books'): 
     return ndb.Key(Book, group) 

    # Search all 
    @classmethod 
    def getAll(cls): 
     q = Book.query(ancestor=cls.bookKey()) 
     q = q.order(Book.title) 
     books = q.fetch(100) 
     return books 

    @classmethod 
    def byId(cls, id): 
     book = Book.get_by_id(long(id), cls.bookKey()) 

    # Get all the Chapters for a book 
    def getChapters(self): 
     chapters = Chapter.query(ancestor=self).order(Chapter.number).fetch(100) 
     return chapters 

class Chapter(ndb.Model): 
    """ All chapters that a book have """ 
    title = ndb.StringProperty(required=True) 
    number = ndb.IntegerProperty(default=1) 
    created = ndb.DateTimeProperty(auto_now_add=True) 

    book = ndb.KeyProperty(kind=Book) 

    # 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(ndb.Model): 
    """ All votes that a book-chapter have """ 
    value = ndb.IntegerProperty(default=1) 

    book = ndb.KeyProperty(kind=Book) 
    chapter = ndb.KeyProperty(kind=Chapter) 

好了,我的疑惑是:

  1. 是這種做法是否正確?
  2. 爲了確保所有實體都使用祖先,我創建的函數bookKey()很適合擁有「虛擬祖先」?
  3. 我必須在Vote類中定義一本書和一章的參考,因爲它是一個外鍵(就像我想的那樣)?
  4. 是否定義了從書中檢索章節的方式?我的意思是,在Chapter類中,函數byBook使用Book類中的函數。或者我必須避免使用其他實體的函數來獲得更乾淨的代碼?
  5. 我該如何檢索所有章節的選票?
  6. 哪一種方法可以獲得特定章節和特定書籍的所有選票總和?

最後,我將顯示一張帶有我所有書籍的表格。在表格中,我想得到每本書的所有選票的總和。例如:

名稱|票選 Sentinel | 30票 女巫| 4票

我怎樣才能得到這個信息,特別是計票。

然後,點擊書名,我想要顯示他所有的章節(那麼當我必須在章模型上使用byBook函數時,我會提出這個章節吧?)。

哪一個是我需要獲得這種數據的GQL?

在此先感謝。

回答

2

好的開始。 GAE的數據存儲有點混亂。因爲它是無模式的,所以我發現處理實體更像處理內存中的對象/數據結構,而不是處理數據庫表。

這裏有幾件事我會做不同的:

  • 看樣子你正在創建一個單一的祖先在你所有的書籍。可怕的想法。在性能方面讓你過度。除非有一些交易操作,否則您需要對不在您當前代碼中的一組書進行操作,這是不對的。

  • 從Book.getChapters()函數看來,您希望將書籍作爲一組章節的祖先。這可能是一個祖先的良好用法。我沒有看到創建章節的代碼,但確保將適當的書籍指定爲祖先。

  • 我只是簡單地將一個投票作爲一個屬性放在書或章中。沒有必要使它成爲一種獨立的類型,您需要發出額外的查詢。

  • 如果每本書的章節數量有限,我會考慮使用StructuredProperty作爲章節。 StructuredProperties本質上是一個父實體(Book)中的結構化數據。你會被Book實體的最大大小(1MB)所限制,但如果它合適的話,它會爲你節省額外查詢的成本,因爲你不會在沒有合適的書的情況下查詢章節。

+0

說多數什麼我可以說,但我想補充一點,如果你想獲得總計和小計沒有組由SQL選項,所以ü通過有環和自己添加的總數(我猜你可以有一個計算字段) – 2013-05-21 15:37:26

+0

謝謝,@dragonx。對於書籍祖先來說,我必須做什麼?當我爲書籍執行getAll()時,我需要指定一個祖先。如果每本書有不同的祖先,只會選擇一本書,不是嗎?當我創作第一章時,我將這本書作爲祖先。在SQL中,投票顯然必須是獨立的,但是在NoSQL中可能不是。一個用戶將進行投票,這會影響到章節,並且通過繼承而產生一本書。如果我將它包含在兩個實體中,我必須爲每個投票管理雙重工作,但可以。我將測試你最後一次關於StructuredProperties的建議。 NoSQL的硬路徑。 ;) – Eagle

+0

祖先只在需要強一致性查詢時才需要。如果你遺漏了祖先,你可以得到所有的書籍。缺點是你的查詢最終是一致的。你需要決定最終一致的行爲是否可以接受。如果這只是爲了瀏覽,那很可能是。 – dragonx