我需要一些独特的属性。我怎样才能做到这一点?
有类似unique=True
的内容吗?
我正在使用Google App Engine for Python。
答案 0 :(得分:24)
Google提供了这样做的功能:
http://code.google.com/appengine/docs/python/datastore/modelclass.html#Model_get_or_insert
Model.get_or_insert(key_name, **kwds)
尝试使用给定的密钥名称获取模型类型的实体。如果存在,get_or_insert()只返回它。如果它不存在,则创建,存储和返回在kwds中具有给定种类,名称和参数的新实体。
get和后续(可能)put被包装在事务中以确保原子性。这意味着get_or_insert()永远不会覆盖现有实体,并且当且仅当不存在具有给定种类和名称的实体时才会插入新实体。
换句话说,get_or_insert()等同于这个Python代码:
def txn():
entity = MyModel.get_by_key_name(key_name, parent=kwds.get('parent'))
if entity is None:
entity = MyModel(key_name=key_name, **kwds)
entity.put()
return entity
return db.run_in_transaction(txn)
<强>参数:强>
KEY_NAME 实体密钥的名称 ** kwds 如果不存在具有指定键名的实例,则传递给模型类的构造函数的关键字参数。如果所需实体具有父级,则需要父参数。
注意:get_or_insert()不接受RPC对象。
该方法返回表示所请求实体的模型类的实例,无论该实体是存在还是由该方法创建。与所有数据存储区操作一样,如果无法完成事务,此方法可能引发TransactionFailedError。
答案 1 :(得分:21)
没有内置约束来确保值是唯一的。但是你可以这样做:
query = MyModel.all(keys_only=True).filter('unique_property', value_to_be_used)
entity = query.get()
if entity:
raise Exception('unique_property must have a unique value!')
我使用keys_only=True
因为它不会为实体提取数据而会略微提高性能。
更有效的方法是使用单独的模型,其中没有字段,其键名由属性名+值组成。然后,您可以使用get_by_key_name
来获取这些复合键名中的一个或多个,如果您获得一个或多个非None
值,则表示存在重复值(并检查哪些值不是{{ 1}},你会知道哪些不是唯一的。)
正如评论中提到的 onebyone 一样,这些方法 - 通过它们先获得,后来的性质 - 运行风险并发问题。从理论上讲,可以在检查现有值之后立即创建实体,然后检查后的代码仍将执行,从而导致重复值。为防止这种情况,您必须使用交易:Transactions - Google App Engine
如果您希望检查具有事务的所有实体的唯一性,则必须使用第一种方法将所有这些实体放在同一组中,这样效率非常低。对于事务,请使用第二种方法:
None
class UniqueConstraint(db.Model):
@classmethod
def check(cls, model, **values):
# Create a pseudo-key for use as an entity group.
parent = db.Key.from_path(model.kind(), 'unique-values')
# Build a list of key names to test.
key_names = []
for key in values:
key_names.append('%s:%s' % (key, values[key]))
def txn():
result = cls.get_by_key_name(key_names, parent)
for test in result:
if test: return False
for key_name in key_names:
uc = cls(key_name=key_name, parent=parent)
uc.put()
return True
return db.run_in_transaction(txn)
将假设每个键/值对必须唯一才能返回成功。该事务将为每种模型使用单个实体组。这样,事务对于几个不同的字段同时是可靠的(对于一个字段,这将更加简单。)此外,即使您在一个或多个模型中具有相同名称的字段,它们也不会与彼此。