Google App Engine分配实体组/父键,唯一约束

时间:2012-10-30 15:17:19

标签: google-app-engine unique-constraint entity-groups

我有一种'顾客'。我想运行一个事务,当一个新的'Customer'即将被插入时,它会锁定整个Kind。事务将首先查询以检查新的“客户”名称是否已存在,然后如果未找到匹配项,则事务的第二部分将运行插入。这样我就强制执行唯一约束(并且还将操作限制为每秒约1次插入)。

我将所有“客户”实体放在同一个实体组中的令人不满意的解决方案是创建一个名为“EntityGroups”的类,其中包含一个名为“CustomersGroup”的记录。这一条记录每次都被用作新创建的“客户”实体的父级,从而将整个类别分组到一个实体组中。

我的问题是:我担心使用像'CustomerGroup'这样的虚拟记录,因为如果发生任何事情并且丢失或删除了,我无法将任何新的'客户'实体分配到同一个组!我想最好为每个'Customer'实体的Parent分配一个静态的任意父项,比如'1111111'?我认为术语是“虚拟根实体”,我该怎么做?

请帮助我提供有关如何最好地处理此事的任何建议!

4 个答案:

答案 0 :(得分:3)

为什么不使用:NDB的get_or_insert:以事务方式检索现有实体或创建新实体。

https://developers.google.com/appengine/docs/python/ndb/modelclass#Model_get_or_insert

答案 1 :(得分:3)

您的CustomerGroup记录不需要存在,因为它可以充当父级。只需手动创建密钥并将其指定为相关记录的父级。

如果它不存在,你不必担心它会被删除!

当您创建模型并将另一个设置为父模型时,系统不会检查(也不需要)该模型实际存在。

例如:

rev_key = ndb.Key('CustomerGroup', '11111', 'Customer', 'New_Customer_Name')

然而,具有关键字:('CustomerGroup', '11111')的模型实际上并不存在,但它仍然可以在祖先链中。

答案 2 :(得分:1)

GrantsV,您可以通过为每个唯一约束创建代理实体并使用跨组事务通过正常写入提交约束来实现此目的。

class UniqueConstraint(db.Model):
  # Consider adding a reference to the owner of the constraint.
  @db.transactional(propagation=db.MANDATORY, xg=True)
  @classmethod
  def reserve(cls, kind, property, value):
    key = cls.__get_key(kind, property, value)
    if db.get(key):
      raise Exception  # Already exists
    cls(key=key).put()

  @db.transactional(propagation=db.MANDATORY, xg=True)
  @classmethod
  def release(cls, kind, property, value):
    db.delete(cls.__get_key(kind, property, value))

  @classmethod
  def __get_key(cls, kind, property, value):
    # Consider using a larger entity group.
    return db.Key.from_path(cls.kind(), '%s:%s:%s' % (kind, property, value))
    # To restrict to 1 insert per second per kind, use:
    # return db.Key.from_path(cls.kind(), kind, cls.kind(), '%s:%s' % (property, value))

答案 3 :(得分:0)

您可以创建父实体,如下所示:

class CustomerParent(ndb.Model):
    pass

然后您实例化并存储您的父实体:

customers_parent = CustomerParent()
customers_parent.put()

最后,当您创建所有客户实体时,请指定父项:

a_customer = Customer(parent=customers_parent.key, ...)
a_customer.put()

希望这有帮助!