正在覆盖NDB Put事务

时间:2014-01-23 00:32:51

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

我有一本字典,我想在整个App Engine上写一个NDB。问题是只写了字典中的最后一项。我想也许写的速度太快了,所以我把睡眠定时器放进了很长的20秒等待,看看会发生什么。我不断刷新数据存储查看器,看到事务写入,然后被下一个事务等覆盖。表开始为空,字典键是唯一的。一个简单的例子:

class Stats(ndb.Model):
    desc= ndb.StringProperty(required = True)
    count= ndb.IntegerProperty(required = True)
    update = ndb.DateTimeProperty(auto_now_add = True)    

class refresh(webapp2.RequestHandler):
   def get(self):

      statsStore = Stats()

      dict = {"test1":0,"test2":1,"test3":2}

      for key in dict:
         statsStore.desc = key
         statsStore.count = dict.get(key)
         statsStore.put()

上面会发生的是,只有最终的字典项才会保留在数据存储区中。再次使用睡眠定时器,我可以看到每个被写入但随后被覆盖。我在本地机器上使用本地开发GAE环境。

感谢帮助。

2 个答案:

答案 0 :(得分:2)

原始代码的问题在于您正在重用相同的实体(模型实例)。

在第一个put()期间,生成数据存储区密钥并将其分配给该实体。然后,以下所有put()调用都使用相同的密钥。

更改它以在每次迭代时创建一个新的模型实例(您在注释中提到的解决方案)将确保每次都生成一个新的数据存储区键。

另一种选择是在调用put()之前用“statsStore.key = None”清除键。但你所做的可能更好。

答案 1 :(得分:1)

不确定你要做什么,但这里有一些希望有用的指针。如果要保存dict,然后通过从数据库中读取来重新使用它,则将字符串更改为text属性,导入json,并使用json.dumps()将dict保存为json字符串值。如果要为dict中的每个元素编写实体,那么您将需要在for循环中移动statsStore类创建行,并通过将每个Stats()类添加到数组来完成循环过程。循环完成后,您可以批量放置数组中的所有实体。这种批处理方法比在循环中包含put()快得多,这通常是一种非常不具备性能的设计选择。如果你只想记录dict中的所有值以供以后参考,并且你有一个可以安全地用作分隔符的值,那么我将在你的循环之前创建两个空数组,并将每个desc和count附加到各自的阵列。一旦在数组外部,您可以通过使用分隔符字符串连接数组,将这些值保存到实体中的两个文本属性。如果你这样做,那么强烈建议使用urllib.quote()在附加它时转义你的desc文本值,以避免与你的分隔符值冲突。

最后请注意:使用StringProperty时,应该小心使用这种类型的进程。您可能很容易超出字符串限制大小,具体取决于项目数和/或desc值的长度。还要记住你在dict中的项目可能不会按照你想要的顺序出现。考虑类似的事情:“for k,v in sorted(mydict.items()):”HTH,stevep

相关问题