How to delete all datastore in Google App Engine?

Does anyone know how to delete all datastore in Google App Engine?

83266 次浏览

If you're talking about the 实时数据存储, open the dashboard for your app (login on appengine) then datastore --> dataviewer, select all the rows for the table you want to delete and hit the delete button (you'll have to do this for all your tables). You can do the same programmatically through the remote_api (but I never used it).

如果你谈论的是 开发数据存储,你只需要删除以下文件: ”./WEB-INF/appengine-generated/local _ db. bin”。下次运行开发服务器时,将再次为您生成该文件,并且您将拥有一个清晰的数据库。

确保事后清理你的项目。

当您开始使用 GoogleApplicationEngine 时,这是一个非常有用的小陷阱。您会发现自己将对象持久化到数据存储中,然后更改持久化实体的 JDO 对象模型,最终导致过时的数据,从而使应用程序到处崩溃。

你可以用网页界面来做。登录到您的帐户,导航与左侧的链接。在数据存储管理中,您可以选择修改和删除数据。使用各自的选项。

If you have a significant amount of data, you need to use a script to delete it. You can use remote_api to clear the datastore from the client side in a straightforward manner, though.

最好的方法是 Nick 建议的远程 API 方法,他是来自 谷歌App Engine工程师,所以相信他。

这并不难做到,最新的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,在应用程序设置启用后,您可以批量删除以及备份您的数据存储通过网络用户界面。

来源

我从 译自: 美国《 http://code.google.com/appengine/articles/remote_api.html 》杂志网站(http://code.google.com/appengine/article/remote _ api.html) 得到这个。

创建交互控制台

First, you need to define an interactive appenginge console. So, create a file called appengine_console.py and enter this:

#!/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 is supposed to be just an abstract class that allows you to iterate over every entity of a given kind, be it to extract their data, or to modify them and store the updated entities back to the datastore.

快跑!

现在,启动 appengine 交互控制台:

$python appengine_console.py <app_id_here>

That should start the interactive console. In it create a subclass of 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 () Run ()

就是这样!

If you have a lot of data, using the web interface could be time consuming. The App Engine 启动器 utility lets you delete everything in one go with the 'Clear datastore on launch' checkbox. This utility is now available for both Windows and Mac (Python framework).

我已经创建了一个外接程序面板,可以与您部署的 App Engine 应用程序一起使用。它在一个下拉列表中列出了数据存储中存在的种类,您可以单击一个按钮来安排“任务”,以删除特定种类的所有实体或简单地删除所有内容。你可在此下载:
Http://code.google.com/p/jobfeed/wiki/nuke

在 Datastore 上处理批量删除的最快、最有效的方法是使用最新的 Google I/O上宣布的新 映射器应用程式编程接口

If your language of choice is 巨蟒, you just have to register your mapper in a Mapreduce.yaml file and define a function like this:

from mapreduce import operation as op
def process(entity):
yield op.db.Delete(entity)

爪哇咖啡上,你应该看一下 这篇文章,它提示了这样一个函数:

@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以来,有一个用于此目的的 数据存储管理特性

You can 清除开发服务器数据存储 when you run the server:

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

You can also abbreviate --clear_datastore with -c.

I was so frustrated about existing solutions for 删除活动数据存储中的所有数据 that I created a small GAE app that can delete quite some amount of data within its 30 seconds.

如何安装等: https://github.com/xamde/xydra

对于 Python,1.3.8包含了一个实验性的管理内置程序

builtins:
- datastore_admin: on

”目前只有 Python 运行时可以使用 Datastore delete。然而,Java 应用程序仍然可以通过创建非默认的 Python 应用程序版本来利用这一特性,该版本支持 app.yaml 中的 Datastore Admin。对 Java 的本地支持将包含在即将发布的版本中。”

实现这一点的零设置方法是向管理服务发送一个执行任意代码的 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())'}))

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秒。

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

我通常不想删除所有的数据存储,所以我提取了/war/WEB-INF/local _ db 的一个干净的副本。放弃源代码管理。它可能只是我,但它似乎即使与开发模式停止,我必须删除物理文件之前,拉它。这是在 Windows 上使用 Eclipse 的 subversion 插件实现的。

为应用程序打开“ Datastore Admin”并启用 Admin。然后,所有的实体将与复选框一起列出。您可以简单地选择不需要的实体并删除它们。

这里: 转到 Datastore Admin,然后选择要删除的实体类型,然后单击“删除”。Mapreduce 会负责删除!

这就是你要找的..。

db.delete(Entry.all(keys_only=True))

Running a keys-only query is much faster than a full fetch, and your quota will take a smaller hit because keys-only queries are considered small ops.

这是 Nick Johnson 的 链接到一个答案进一步描述。

下面是截断表的端到端 REST API 解决方案..。

我设置了一个 REST API 来处理数据库事务,其中路由被直接映射到适当的模型/操作。这可以通过输入正确的 url ( example.com/inventory/truncate )并登录来调用。

路线是这样的:

Route('/inventory/truncate', DataHandler, defaults={'_model':'Inventory', '_action':'truncate'})

接头人是这样的:

class DataHandler(webapp2.RequestHandler):
@basic_auth
def delete(self, **defaults):
model = defaults.get('_model')
action = defaults.get('_action')
module = __import__('api.models', fromlist=[model])
model_instance = getattr(module, model)()
result = getattr(model_instance, action)()

它首先动态加载模型(即在 api.model 下找到 Inventory) ,然后调用 action 参数中指定的正确方法(Inventory.truncate ())。

@ basic _ auth 是一个为敏感操作(即 POST/DELETE)提供身份验证的装饰器/包装器。如果您担心安全问题,还有一个 设计师可用。

最后,这一行动被称为:

def truncate(self):
db.delete(Inventory.all(keys_only=True))

看起来很神奇,但实际上很简单。最好的部分是,delete ()可以通过向模型添加另一个操作来重用于处理删除一个或多个结果。

对于开发服务器,不需要通过谷歌应用程序引擎启动程序运行服务器,你可以在终端上运行它,比如:

Dev _ appserver.py —— port = [ portnumber ]—— clear _ datastore = yes [ name of application ]

例如: 我的应用程序“ reader”在端口15080上运行。修改代码并重新启动服务器之后,我只运行“ dev _ appserver.py —— port = 15080—— clear _ datastore = yes reader”。

It's good for me.

补充关于最近事态发展的答案。

谷歌最近增加了数据存储管理功能。您可以备份,删除或复制您的实体到另一个应用程序使用这个控制台。

https://developers.google.com/appengine/docs/adminconsole/datastoreadmin#Deleting_Entities_in_Bulk

如果您使用的是 ndb,那么清除数据存储的方法是:

ndb.delete_multi(ndb.Query(default_options=ndb.QueryOptions(keys_only=True)))

对于应用程序引擎上的任何数据存储,而不是本地数据存储,您可以使用 新的数据存储应用程序接口

我编写了一个脚本,删除所有非内建的实体。API 的变化非常快,所以作为参考,我在提交 990ab5c7f2063e8147bcc56ee22836fd3d6e15b时克隆了它

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()

您可以通过逐一删除所有类型来删除所有数据存储。 with google appengine dash board. Please follow these Steps.

  1. 登入 https://console.cloud.google.com/datastore/settings
  2. 单击 Open Datastore Admin。(如果未启用,则启用它。)
  3. 选择所有实体并按删除键。(此步骤运行一个用于删除所有选定种类的 map reduce 作业。)

有关详细信息,请参阅此图像 http://storage.googleapis.com/bnifsc/Screenshot%20from%202015-01-31%2023%3A58%3A41.png

有几种方法可以用来从 App Engine 的 Datastore 中删除条目:

enter image description here

  1. 首先,考虑是否真的需要删除条目。这是昂贵的,它可能更便宜,不删除他们。

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

  3. 您可以交互式地使用 RemoteAPI 和删除条目。

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

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

  6. 或者,您可以使用 Mapreduce 来获得更健壮、更花哨的内容。

这些方法中的每一个都在下面的博客文章中解释: Http://www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore

希望能有帮助!

  • 继续使用 svpino 的想法,重用标记为 delete 的记录是明智的。(他的想法不是删除,而是将未使用的记录标记为“已删除”)。少量的 cache/memcache 来处理工作副本,并且只写状态差异(在期望的任务之前和之后)到数据存储将使它更好。对于大型任务,如果 memcache 消失,可以将中间差异块写入数据存储,以避免数据丢失。为了防止丢失,可以检查 memcached 结果的完整性/存在性,并重新启动任务(或需要的部分)以重复丢失的计算。当数据差异写入数据存储时,所需的计算被丢弃在队列中。

  • 另一种类似于映射约简的思想是将实体类分解为几个不同的实体类,从而将其作为单个实体类向最终用户收集在一起并可见。条目只标记为“已删除”。当每个碎片的“已删除”条目数量超过某个限制时,“活的”条目将在其他碎片之间分布,这个碎片将永远关闭,然后从开发控制台手动删除(猜测成本较低)。

  • 它可以通过大块的查询来删除大量的记录,而不会出现故障(至少在本地工作) ,当时间结束时还可以继续下一次尝试:


qdelete.getFetchPlan().setFetchSize(100);


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

对于所有需要开发服务器快速解决方案的人(截至2016年2月写作时) :

  1. 停止开发服务器。
  2. 删除 目标目录。
  3. Rebuild the project.

这将从数据存储中删除所有数据。

为了咖啡

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);

在开发服务器中工作良好

You have 2 simple ways,

# 1: 为了节省成本,删除整个项目

#2: using ts-datastore-orm:

Https://www.npmjs.com/package/ts-datastore-orm await Entity.truncate(); 截断可以每秒删除约1K 行

下面是我如何天真地从一个香草 谷歌云壳(没有 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

截至2022年,据我所知,有两种方法可以从(较大的)数据存储中删除某种数据。Google 推荐使用 数据流模板。这个模板基本上将每个实体一个一个地拉到一个 GQL 查询,然后删除它。有趣的是,如果您正在删除大量行(> 1000万) ,您将遇到数据存储问题; 因为它将无法提供足够的容量,并且您对数据存储的操作将开始超时。然而,只有那种你大量删除将受到影响。

如果你的行数少于10m,你可以使用下面的脚本:

import (
"cloud.google.com/go/datastore"
"context"
"fmt"
"google.golang.org/api/option"
"log"
"strings"
"sync"
"time"
)


const (
batchSize       = 10000 // number of keys to get in a single batch
deleteBatchSize = 500   // number of keys to delete in a single batch
projectID       = "name-of-your-GCP-project"
serviceAccount  = "path-to-sa-file"
table           = "kind-to-delete"
)


func min(a, b int) int {
if a < b {
return a
}
return b
}


func deleteBatch(table string) int {


ctx := context.Background()
client, err := datastore.NewClient(ctx, projectID, option.WithCredentialsFile(serviceAccount))
if err != nil {
log.Fatalf("Failed to open client: %v", err)
}
defer client.Close()
        

query := datastore.NewQuery(table).KeysOnly().Limit(batchSize)


keys, err := client.GetAll(ctx, query, nil)
if err != nil {
fmt.Printf("%s Failed to get %d keys : %v\n", table, batchSize, err)
return -1
}


var wg sync.WaitGroup
for i := 0; i < len(keys); i += deleteBatchSize {
wg.Add(1)
go func(i int) {
batch := keys[i : i+min(len(keys)-i, deleteBatchSize)]
if err := client.DeleteMulti(ctx, batch); err != nil {
// not a big problem, we'll get them next time ;)
fmt.Printf("%s Failed to delete multi: %v", table, err)
}
wg.Done()
}(i)
}


wg.Wait()
return len(keys)
}


func main() {


var globalStartTime = time.Now()


fmt.Printf("Deleting \033[1m%s\033[0m\n", table)
for {
startTime := time.Now()
count := deleteBatch(table)
if count >= 0 {
rate := float64(count) / time.Since(startTime).Seconds()
fmt.Printf("Deleted %d keys from %s in %.2fs, rate %.2f keys/s\n", count, table, time.Since(startTime).Seconds(), rate)
if count == 0 {
fmt.Printf("%s is now clear.\n", table)
break
}
} else {
fmt.Printf("Retrying after short cooldown\n")
time.Sleep(10 * time.Second)
}
}


fmt.Printf("Total time taken %s.\n", time.Since(globalStartTime))
}