App Engine通过实例本身在重复的KeyProperty中编辑实例

时间:2015-11-25 11:17:28

标签: google-app-engine google-cloud-datastore app-engine-ndb google-app-engine-python

假设我有以下型号:

class Author(ndb.Model)
    books = ndb.KeyProperty(kind='Book', repeated=True)

class Book(ndb.Model)
    title = ndb.StringProperty()

因此,在某一时刻,您会有一位作者列出n本书。

问题: 当我正在编辑一本书时,如何在不引用“当前”作者的情况下更改作者?我是否需要在KeyProperty上添加Book的反向关系?

更改作者时,我必须从旧作者列表中删除该书并将其添加到新书中。这感觉有点麻烦。还有更好的方法吗?

加分问题:如果图书被删除怎么办?作者的书籍列表中将有None值。我必须删除它吗?

注意:我正在使用重复的KeyProperty,因为这样可以轻松订购书籍,在我看来这很重要。

2 个答案:

答案 0 :(得分:1)

  

当我正在编辑一本书时,如何在不引用“当前”作者的情况下更改作者?

您可以在保存实体之前使用ndb.Model.allocate_ids保留密钥

  

我是否需要在Book上添加与KeyProperty的反向关系?

鉴于您的模型,添加反向查找键可以让您的生活更轻松

  

如果书籍被删除怎么办?作者的书籍列表中将包含无值。我必须删除它吗?

在这种情况下,Auther.books中的密钥不会自动变为空。你必须自己删除它。

  

我正在使用重复的KeyProperty,因为这样可以轻松订购书籍,在我看来这很重要。

潜在的问题是实体的大小限制为1mb。如果作者是非常多产的作家(例如Edwy Searles Brooks有800多篇已发表的作品),那么它可以超出限制。

我会这样设计模型:

class Author(ndb.Model):
    name = ndb.StringProperty()

class Book(ndb.Model):
    authors = ndb.KeyProperty('Author', required=True)  # Usually it is at most a couple of authors  
    title = ndb.StringProperty()

要查找ID为1234的特定作者所写的所有书籍,您可以

  Book.query(Book.authors == ndb.Key('Author', 1234)).fetch()

显然,书籍的订购必须明确存储,我建议第三个实体来跟踪这些信息:

class BookList(ndb.Model):
  name = ndb.StringProperty()
  book_keys = ndb.KeyProperty(kind='Book', repeated=True)

然后你可以用这种方式检索书籍

stephen_king_book_list = stephen_king_book_list_key.get()
books = ndb.get_multi(stephen_king_book_list.book_keys)
# Some of key can lead to None if the underlying book is already deleted
# You can define some background job to sweep clean the list from time to time 
# But let filter out the bad guys first 
books = [b for b in books if b]  

如果您认为您的列表将会非常长,您可以将列表分解为链接列表结构等段

class BookList(ndb.Model):
  prev_segment = ndb.KeyProperty(kind='BookList', required=False)
  next_segment = ndb.KeyProperty(kind='BookList', required=False)
  name = ndb.StringProperty()
  book_keys = ndb.KeyProperty(kind='Book', repeated=True)

您可以通过以下方式轻松找到第一段:

  starting_point = BookList.query(BookList.name == 'Stephen_King',
     BookList.prev_segment == None
  ).fetch()

当然,如果插入非常频繁,您可能希望使用替代结构来保存图书清单

答案 1 :(得分:0)

你的人际关系真的是错误的。你应该在Book上有一个KeyProperty指向Author;然后,如果您想查询单个作者的所有书籍,您可以在作者密钥上查询。