如何在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个回答

69
如果您谈论的是实时数据存储,请打开您应用程序的仪表板(在AppEngine上登录),然后进入数据存储-->数据查看器,在要删除的表中选择所有行,然后点击删除按钮(对于所有表格都需要这样做)。 您也可以通过远程API以编程方式执行相同操作(但我从未使用过)。
如果您谈论的是开发数据存储,则只需删除以下文件:"./WEB-INF/appengine-generated/local_db.bin"。下次运行开发服务器时,该文件将为您生成,并且您将获得一个清晰的数据库。
请务必在此之后清理您的项目。
当您开始使用Google Application Engine时,这是其中一个小技巧,您会发现自己将对象持久化到数据存储中,然后更改可持久化实体的JDO对象模型,最终得到过时的数据,这将导致您的应用程序无法正常运行。

16
dev_appserver.py有一个“-c”参数,可以从开发数据存储中删除数据。 - svrist
1
@svrist 但这仅适用于Python应用程序引擎。有人知道如何在Java中快捷方式执行吗?(同时,JohnIdol的建议也很好用。) - mgiuca
2
谢谢@John:在MAC OSX中确切的路径在哪里? - George Nguyen
3
在Windows中,路径在哪里? - Shane Best
2
@ShaneBest 在Windows中的路径大概是./target/yourappid-1.0-SNAPSHOT/WEB-INF/appengine-generated/local_db.bin。 - morpheus

57

最佳方法是远程API方法,正如来自GoogleApp Engine工程师Nick所建议的那样,所以请相信他。

这并不难做,最新的1.2.5 SDK提供了remote_shell_api.py。所以去下载新的SDK,然后按照以下步骤操作:

  • 在命令行中连接远程服务器:remote_shell_api.py yourapp /remote_api Shell会要求您输入登录信息,如果授权,将为您创建一个Python shell。您需要在app.yaml中设置/remote_api的URL处理程序。

  • 获取您想要删除的实体,代码看起来像这样:

    from models import Entry
    query = Entry.all(keys_only=True)
    entries =query.fetch(1000)
    db.delete(entries)
    \# This could bulk delete 1000 entities a time

更新于2013年10月28日:

  • remote_shell_api.py已被remote_api_shell.py所取代,您应该使用remote_api_shell.py -s your_app_id.appspot.com进行连接,根据文档

  • 有一个新的实验性功能Datastore Admin,在应用程序设置中启用后,您可以通过Web界面批量删除和备份数据存储。


17
实际上,您不需要获取(fetch)。只需使用db.delete(Entry.all())即可完成。 - Erin
4
你需要将此操作分成500个实体集,否则会出现以下错误:BadRequestError: 无法在单次调用中删除超过500个实体。 - marcc
1
仅供参考,如果要使用远程API,您需要在应用程序中首先启用它,在您的YAML文件中使用builtins:-remote_api。更多信息请访问https://developers.google.com/appengine/articles/remote_api。 - Zaffiro
2
当调用Entry.all()时,请至少添加'keys_only=True'。如果您不需要检查数据,则无需获取整个条目。否则,您只是浪费计算周期。 - Evan Plaice
1
+1 ... 但是:截至2013年,remote_shell_api.py文件已不存在。当前的脚本名称为remote_api_shell.py。另外,如果你使用ndb(这是大多数人现在使用的),推荐使用ndb.delete_multi(model.Entry.query().fetch(keys_only=True)) - Uri London
显示剩余3条评论

27
使用最新的Google I/O宣布的mapper API是处理Datastore批量删除的最快和高效的方法。
如果您选择的语言是Python,您只需在mapreduce.yaml文件中注册映射器并定义如下函数即可:
from mapreduce import operation as op
def process(entity):
 yield op.db.Delete(entity)

Java中,你应该查看这篇文章,它建议使用以下函数:

@Override
public void map(Key key, Entity value, Context context) {
    log.info("Adding key to deletion pool: " + key);
    DatastoreMutationPool mutationPool = this.getAppEngineContext(context)
            .getMutationPool();
    mutationPool.delete(value.getKey());
}

编辑:
自SDK 1.3.8版本以来,有一个数据存储管理员功能可用于此目的。


27

在运行服务器时,您可以清除开发服务器数据存储器:

/path/to/dev_appserver.py --clear_datastore=yes myapp

您也可以使用-c缩写替代--clear_datastore

您可以查看此处的文档了解更多信息。


5
不确定是否是最近的事情,但现在实际的语法是 /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/(注意 'yes')。 - Melllvar
这是在开发过程中重复删除数据存储的最有用的方式。随着选项变得越来越过时,值得强调的是,在2018年7月,该标志仍然存在,并且适用于通过gcloud CLI安装的dev_appserver。 - Michael
在 Google Cloud SDK 的版本 270.0.0 中,“--clear_datastore=yes” 仍然可以使用等号。 - franksands

15

如果你拥有大量的数据需要删除,那么你需要使用脚本来完成这项任务。通过 remote_api ,你可以轻松地从客户端清除 datastore 数据库内容。


11

请前往Datastore管理员,选择您想删除的实体类型,然后单击删除。Mapreduce将负责删除!


截至2022年5月,我不再看到这个选项: - AAP

10

您可以使用多种方法从App Engine的Datastore中删除条目:

这里输入图片描述

  1. 首先,考虑是否真的需要删除条目。这很耗费资源,也许不删除它们会更便宜。

  2. 您可以使用Datastore Admin手动删除所有条目。

  3. 您可以使用远程API交互式地删除条目。

  4. 您可以使用几行代码以编程方式删除条目。

  5. 您可以使用任务队列和游标批量删除它们。

  6. 或者您可以使用Mapreduce来获得更强大和更华丽的功能。

以下每种方法都在以下博客文章中解释: http://www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore

希望对您有所帮助!


6
零设置的方法是向您正在运行的应用程序已经自动拥有的管理服务发送一个执行任意代码的HTTP请求:
import urllib
import urllib2

urllib2.urlopen('http://localhost:8080/_ah/admin/interactive/execute',
    data = urllib.urlencode({'code' : 'from google.appengine.ext import db\n' +
                                      'db.delete(db.Query())'}))

这只适用于开发服务器,有生产环境的等价物吗? - Gady

3

对于Python,1.3.8版本包含了一个实验性的内置管理员。他们:“在您的app.yaml文件中启用以下内置功能:”

builtins:
- datastore_admin: on

"目前只有Python运行时支持数据存储删除。但是,Java应用程序仍然可以通过创建非默认的Python应用程序版本,在app.yaml中启用Datastore Admin来利用此功能。原生的Java支持将在即将发布的版本中包含。"

在 app.yaml 中添加配置会引发错误。相反,我们可以在“管理”部分的“应用程序设置”页面中启用它。有一个按钮可以启用它。 - Sundeep

3

来源

我从 http://code.google.com/appengine/articles/remote_api.html 获取了此内容。

创建交互式控制台

首先,您需要定义一个交互式的appengine控制台。因此,创建一个名为appengine_console.py的文件并输入以下内容:

#!/usr/bin/python
import code
import getpass
import sys

# These are for my OSX installation. Change it to match your google_appengine paths. sys.path.append("/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine")
sys.path.append("/Applications/GoogleAppEngineLauncher.app/Contents/Resources/GoogleAppEngine-default.bundle/Contents/Resources/google_appengine/lib/yaml/lib")

from google.appengine.ext.remote_api import remote_api_stub
from google.appengine.ext import db

def auth_func():
  return raw_input('Username:'), getpass.getpass('Password:')

if len(sys.argv) < 2:
  print "Usage: %s app_id [host]" % (sys.argv[0],)
app_id = sys.argv[1]
if len(sys.argv) > 2:
  host = sys.argv[2]
else:
  host = '%s.appspot.com' % app_id

remote_api_stub.ConfigureRemoteDatastore(app_id, '/remote_api', auth_func, host)

code.interact('App Engine interactive console for %s' % (app_id,), None, locals())

创建Mapper基类

一旦这个基类创建好了,就可以创建Mapper类。我创建了一个名为utils.py的新文件,并添加了以下内容:

class Mapper(object):
  # Subclasses should replace this with a model class (eg, model.Person).
  KIND = None

  # Subclasses can replace this with a list of (property, value) tuples to filter by.
  FILTERS = []

  def map(self, entity):
    """Updates a single entity.

    Implementers should return a tuple containing two iterables (to_update, to_delete).
    """
    return ([], [])

  def get_query(self):
    """Returns a query over the specified kind, with any appropriate filters applied."""
    q = self.KIND.all()
    for prop, value in self.FILTERS:
      q.filter("%s =" % prop, value)
    q.order("__key__")
    return q

  def run(self, batch_size=100):
    """Executes the map procedure over all matching entities."""
    q = self.get_query()
    entities = q.fetch(batch_size)
    while entities:
      to_put = []
      to_delete = []
      for entity in entities:
        map_updates, map_deletes = self.map(entity)
        to_put.extend(map_updates)
        to_delete.extend(map_deletes)
      if to_put:
        db.put(to_put)
      if to_delete:
        db.delete(to_delete)
      q = self.get_query()
      q.filter("__key__ >", entities[-1].key())
      entities = q.fetch(batch_size)

Mapper是一个抽象类,允许您迭代给定类型的每个实体,无论是提取它们的数据还是修改它们并将更新后的实体存储回数据存储区。



开始使用吧!

现在,启动您的App Engine交互式控制台:

$python appengine_console.py <app_id_here>

这应该会启动交互式控制台。在其中创建一个 Model 的子类:

from utils import Mapper
# import your model class here 
class MyModelDeleter(Mapper):
    KIND = <model_name_here>

    def map(self, entity):
        return ([], [entity])

最后,在您的交互式控制台中运行它:

mapper = MyModelDeleter() mapper.run()

就这样!


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