NDB - 删除密钥列表的最有效方法

时间:2014-08-07 00:39:12

标签: python-2.7 google-app-engine google-cloud-datastore app-engine-ndb

我相信我需要使用ndb.delete_multi,但我很困惑如何让它适用于特定的一组密钥以及它是否是最有效的方法。将Python 2.7与Google App Engine结合使用。

首先,我正在收集我要删除的密钥。我不想删除所有内容,只删除那些1小时或更长时间的条目。为此,我首先收集符合此标准的密钥列表。

cs = ChannelStore()
delMsgKeys = []
for x in cs.allMessages():
   current = datetime.datetime.now()
   recordTime = x.channelMessageCreated
   timeDiffSecs = (current - recordTime).total_seconds()
   timeDiff = (timeDiffSecs/60)/60
   if timeDiff >=1:
      delMsgKeys.append(x.key.id())
ndb.delete_multi(?????)

cs.allMessages()的定义:

def allMessages(self):
        return ChannelStore.query().fetch()

首先,这总体上是最有效的方法吗?其次,如何使用我使用ndb.delete_multi语句创建的密钥列表?

--- ----更新

ndb.delete_multi的问题与我传递的密钥有关。在上面发布的代码中,密钥应该按如下方式存储:

delMsgKeys.append(x.key)

用上面的ndb.delete_multi工作。

1 个答案:

答案 0 :(得分:6)

根据NDB documentation,您只需将密钥列表传递给ndb.delete_multi,因此根据您的代码,这应该有效:

ndb.delete_multi(delMsgKeys)

我不确定单个ndb.delete_multi()电话中可以传递的密钥数量的限制是多少。

对于此查询:

ChannelStore.query().fetch()

您可以添加实体属性,以便在创建/更新实体时通过添加auto_now = Truemore documentation here)来存储时间戳。然后使用timestamp属性,您可以查询以下内容:

sixty_mins_ago = datetime.datetime.now()- datetime.timedelta(minutes = 60)
qry = ChannelStore.query()
list_of_keys = qry.filter(ChannelStore.timestamp < sixty_mins_ago).fetch(keys_only = True)

由于您不需要实体,因此keys_only提取会更便宜。当然,此代码假设您的ChannelStore模型具有timestamp属性,因此您的模型必须是这样的:

class ChannelStore(ndb.model):
    #other properties go here
    timestamp = ndb.DateTimeProperty(auto_now = True)

将所有内容放在一起,这样的内容可能适用于上面的代码块:

from models import ChannelStore
from google.appengine.ext import ndb
from datetime import datetime, timedelta
# other imports

def delete_old_entities():
    sixty_mins_ago = datetime.now() - timedelta(minutes = 60)
    qry = ChannelStore.query()
    qry = qry.filter(ChannelStore.timestamp < sixty_mins_ago)
    list_of_keys = qry.fetch(keys_only = True)
    ndb.delete_multi(list_of_keys)

如果您必须删除大量密钥并且在ndb.delete_multi调用时遇到某种API限制,则可以将delete_old_entities()方法更改为以下内容:

def delete_old_entities():
    sixty_mins_ago = datetime.datetime.now() - datetime.timedelta(minutes = 60)
    qry = ChannelStore.query()
    qry = qry.filter(ChannelStore.timestamp < sixty_mins_ago)
    list_of_keys = qry.fetch(keys_only = True)

    while list_of_keys:
        # delete 100 at a time
        ndb.delete_multi(list_of_keys[:100])
        list_of_keys = list_of_keys[100:]