在数据存储区中,对如何将key_names列表作为参数传递给somemodel.get_or_insert()感到困惑?

时间:2010-04-01 07:46:44

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

是否有关于如何将key_names列表传递给Model.get_or_insert()的示例?

我的问题:

使用ParentLayer的方法我想让孩子们。

Child类的新(或可编辑)实体的key_names将来自以下列表:

namesList = ["picture1","picture2"]

所以我应该能够使用父类的方法构建一个key_names列表,如下所示:

class ParentLayer(db.Model):

 def getOrMakeChildren(self, namesList):
            keyslist = [ db.Key.from_path( 'Child' , name , parent = self.key() ) for name in namesList ]

接下来的问题是我只想根据上面定义的keylist获取get_or_insert实体:

            childrenEntitiesList = Child.get_or_insert(keyslist) # no works?

以下尝试也没有奏效:

            #childrenEntitiesList = Child.get_or_insert(keyslist, parent = u'TEST') 
            #childrenEntitiesList = Child.get_or_insert(keyslist, parent=self.key().name() ) 
            #childrenEntitiesList = Child.get_or_insert(keyslist, parent=self.key() 

1 个答案:

答案 0 :(得分:3)

get_or_insert必须使用事务才能以原子方式返回或创建所请求的实体,并且您无法在多个实体上执行单个事务。此外,get_or_insert接受构造函数的关键字参数,并且没有简单的方法为每个参数指定不同的集合。

如果你只想get_or_insert多个键,你可以这样做:

entities = [Child.get_or_insert(k) for k in keylist]

如上所述,这将需要每个实体的交易。如果您希望相关实体通常存在,则替代版本的get_or_insert可能对您更有用(也更有效):

def _get_or_insert_tx(key, properties):
  """When run in a transaction, fetches or creates an entity atomically."""
  entity = db.get(key)
  if not entity:
    entity = db.class_for_kind(key.kind())(key=key, *properties)
    entity.put()
  return entity

def get_or_insert_multiple(args):
  """Fetches or creates multiple entities.

  Args:
    args: A list of (key, dict-of-properties) tuples
  Returns:
    A list of entities, in the same order as args.
  """
  # First, try and fetch them in a batch, outside the transaction
  entities = db.get([x[0] for x in args])
  # Now, transactionally create or fetch each missing one
  for i in range(len(entities)):
    if entities[i] is None:
      entities[i] = db.run_in_transaction(_get_or_insert_tx, *args[i])
  return entities

此代码将首先尝试批量提取您要创建的所有实体,然后仅针对尚不存在的实体执行事务。在最好的情况下,它只进行一次批量处理;在最坏的情况下,它会为每个实体执行批处理后跟事务。请注意,与内置的get_or_insert不同,这个获取键而不是键名 - 因为这是您使用的语法。

这里正在使用:

entities = get_or_insert_multiple([(k, {}) for k in keys])

请注意每个实体的空字典,因为您没有指定要传递给新实体的构造函数的任何属性。