1

好的,自从我从 SQL 迁移到 noSQL HDR 以来,我遇到了一个小实现问题。

我有一个名为 page 的模型:

class Page(db.Model):
    url = db.StringProperty(required=True)
    title = db.StringProperty()
    enable_login = db.BooleanProperty(required=True, default=True)
    owner = db.ReferenceProperty(Person, collection_name = 'pages')
    date_created = db.DateTimeProperty(auto_now_add=True)
    date_edited = db.DateTimeProperty(auto_now=True)

每次用户注册时,都会创建一个带有唯一url 的页面,该 url 不用作 key_name,原因有几个,我愿意讨论。

交易内部:

unique_url=hashlib.md5(str(person.key())).hexdigest()
page = Page(key_name=unique_url,parent=person, owner=person, title="Home page", name=person.nick_name, url=unique_url)

现在,当用户尝试更新他的页面 url 时,我的问题就出现了。用户只允许更改他的页面 url 一次。用户发布一个新的页面 url,然后服务器检查该 url 是否存在,如果不存在则更新用户页面。

由于我不想要任何重复的网址,因此再次在交易中:

def validate_page_properties(self, page):
  if not re.match("\A[A-Za-z]+\Z", page.url) or len(page.url) < 4 or len(page.url) > 20:
    return False
  page = Page.all().filter("url =",page.url).get()

错误:

Only ancestor queries are allowed inside transactions.

我怎样才能克服这个实现错误?

我尝试将 url 设置为 key_name,因为它是唯一的(强制执行的),但我仍然需要完整的密钥,因为每个页面的父级都是用户。我可以更改为没有父页面的页面,但这可能会在以后再次对我可能需要的事务造成问题。

有什么建议么?我在这里错过了什么吗?

4

1 回答 1

1

首先,您应该了解GAE 事务以及在事务中可以做什么

在您的情况下,您已经将一个人设置为页面的父级,因此您应该只在查询中设置:

 page = Page.all().ancestor(person).filter("url =",page.url).get()

更新:您不能使用人员范围的事务,同时检查全局唯一的用户生成的字符串。要么你有一个字符串是个人唯一的(=废话),要么范围必须是全局的。您可以通过以下方式实现:

  1. 使用全局父级 - 具有单个实体 UniqueUrlParent,它是所有用户提交的 Url 的父级。这将成为一个瓶颈,因为写入限制为每个实体组 5writes/s(您只有一个全局的)。
  2. 使用 Urls 作为键 - 但你说你不想这样做。请详细说明为什么不呢?您可以使用某种两种方式的散列来不使这种人类可读。
于 2012-12-17T11:14:52.343 回答