如何在Google App Engine中删除所有数据存储?

124

2
db.delete(db.Query(keys_only=True))。更多细节请参见https://dev59.com/YHNA5IYBdhLWcg3wL6oc#10856555。 - Evan Plaice
4
如@systempuntoout在下面指出的,GAE现在有一个Datastore Admin界面,可以批量删除实体等操作,无需进行任何编码。这个功能应该被突出显示在此处,而不是被埋在第三条评论中。 - ralfoide
数据存储管理器无法正常工作(页面加载了一个不存在的主机的 iframe),因此我们仍然需要使用 db.delete 方法。 - user153275
要删除开发服务器上的所有数据,请在cmd提示符下执行以下操作:/path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/,其中myappname是包含应用程序app.yaml文件的目录。您需要切换到此目录路径。 来源:Steven Almeroth和Melllvar的答案 - gsinha
30个回答

0

针对Java

DatastoreService db = DatastoreServiceFactory.getDatastoreService();
List<Key> keys = new ArrayList<Key>();
for(Entity e : db.prepare(new Query().setKeysOnly()).asIterable())
    keys.add(e.getKey());
db.delete(keys);

在开发服务器上运行良好


顺便提一下,这将遇到Firestore的限制,即无法对超过500个实体进行多操作。因此,如果没有某种分页方式,该解决方案就不完整。 - OscarVanL

0
对于任何在应用引擎上而不是本地的数据存储,您可以使用新的Datastore API。这里是入门指南
我编写了一个脚本,用于删除所有非内置实体。由于API正在快速更改,因此作为参考,我在提交990ab5c7f2063e8147bcc56ee222836fd3d6e15b时进行了克隆。
from gcloud import datastore
from gcloud.datastore import SCOPE
from gcloud.datastore.connection import Connection
from gcloud.datastore import query

from oauth2client import client

def get_connection():
  client_email = 'XXXXXXXX@developer.gserviceaccount.com'
  private_key_string = open('/path/to/yourfile.p12', 'rb').read()

  svc_account_credentials = client.SignedJwtAssertionCredentials(
    service_account_name=client_email,
    private_key=private_key_string,
    scope=SCOPE)

  return Connection(credentials=svc_account_credentials)


def connect_to_dataset(dataset_id):
  connection = get_connection()
  datastore.set_default_connection(connection)
  datastore.set_default_dataset_id(dataset_id)

if __name__ == "__main__":
  connect_to_dataset(DATASET_NAME)
  gae_entity_query = query.Query()
  gae_entity_query.keys_only()
  for entity in gae_entity_query.fetch():
    if entity.kind[0] != '_':
      print entity.kind
      entity.key.delete()

0

PHP变体:

import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.DatastoreServiceFactory;

define('DATASTORE_SERVICE', DatastoreServiceFactory::getDatastoreService());

function get_all($kind) {
    $query = new Query($kind);
    $prepared = DATASTORE_SERVICE->prepare($query);
    return $prepared->asIterable();
}

function delete_all($kind, $amount = 0) {
    if ($entities = get_all($kind)) {
        $r = $t = 0;
        $delete = array();
        foreach ($entities as $entity) {
            if ($r < 500) {
                $delete[] = $entity->getKey();
            } else {
                DATASTORE_SERVICE->delete($delete);
                $delete = array();
                $r = -1;
            }
            $r++; $t++;
            if ($amount && $amount < $t) break;
        }
        if ($delete) {
            DATASTORE_SERVICE->delete($delete);
        }
    }
}

是的,这需要时间,而且30秒是一个限制。我正在考虑放置一个ajax应用程序示例来自动化超过30秒。


这甚至不是有效的PHP代码。import?将常量定义为对象实例? - Josh J

0
  • 延续svpino的想法,重复使用标记为删除的记录是明智的。(他的想法不是删除,而是将未使用的记录标记为“已删除”)。使用一些缓存/内存缓存来处理工作副本,并仅将状态的差异(所需任务之前和之后)写入数据存储区,这将使其更好。对于大型任务,可以将中间差异块写入数据存储区,以避免如果内存缓存消失而导致数据丢失。为了使其无损失,可以检查memcached结果的完整性/存在性并重新启动任务(或所需部分)以重复缺失的计算。当数据差异被写入数据存储区时,队列中的所需计算将被丢弃。

  • 类似于MapReduce的另一个想法是将实体类型分片到几个不同的实体类型中,以便它们可以被收集在一起,并作为单个实体类型对最终用户可见。条目仅标记为“已删除”。当每个分片中的“已删除”条目数量超过某个限制时,“活动”的条目将在其他分片之间分配,然后该分片将永久关闭,然后手动从开发控制台中删除(猜测成本较低)更新:似乎控制台上没有删除表,只能按常规价格逐条删除记录。

  • 可以通过查询以大块方式删除一组记录,而不会导致GAE失败(至少在本地工作),并且当时间结束时可以继续下一次尝试:


    qdelete.getFetchPlan().setFetchSize(100);

    while (true)
    {
        long result = qdelete.deletePersistentAll(candidates);
        LOG.log(Level.INFO, String.format("deleted: %d", result));
        if (result <= 0)
            break;
    }
  • 有时候,在主表中创建额外的字段,而不是将候选项(相关记录)放入单独的表中,也是很有用的。是的,该字段可以是未索引/序列化数组,计算成本很小。

0
for amodel in db.Model.__subclasses__():
                dela=[]
                print amodel
                try:
                    m = amodel()
                    mq = m.all()
                    print mq.count()
                    for mw in mq:
                        dela.append(mw)
                    db.delete(dela)
            #~ print len(dela)

                except:
                    pass

0
如果您正在使用ndb,那么对我有效的清除数据存储的方法是:
ndb.delete_multi(ndb.Query(default_options=ndb.QueryOptions(keys_only=True)))

1
我认为这不会起作用。Appengine 抱怨 抱歉,意外错误:种类“__Stat_Kind__”已被保留。 这似乎是 appengine 有一些内部统计实体可以通过此方法公开(可能是他们的一个错误?) - xjq233p_1

0

对于所有需要快速解决开发服务器问题的人(截至2016年2月):

  1. 停止开发服务器。
  2. 删除target目录。
  3. 重新构建项目。

这将清除数据存储中的所有数据。


0

0
我对现有的删除实时数据存储中的所有数据解决方案感到非常沮丧,因此我创建了一个小型的GAE应用程序,在其30秒内可以删除相当大量的数据。
安装方法等详见:https://github.com/xamde/xydra

0

这是我如何在一个纯净的 Google Cloud Shell(无 GAE)中使用 python3 做到的:

from google.cloud import datastore
client = datastore.Client()
query.keys_only()
for counter, entity in enumerate(query.fetch()):
    if entity.kind.startswith('_'):  # skip reserved kinds
        continue
    print(f"{counter}: {entity.key}")
    client.delete(entity.key)

即使处理的键数量相对较小,这也需要很长时间,但它可以正常工作。

有关Python客户端库的更多信息:https://googleapis.dev/python/datastore/latest/client.html


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接