有谁知道如何删除Google App Engine中的所有数据存储区?
29 回答
如果您正在谈论实时数据存储,请打开您的应用程序的仪表板(在 appengine 上登录),然后打开数据存储 --> 数据查看器,选择要删除的表的所有行并点击删除按钮(您必须对所有桌子执行此操作)。您可以通过 remote_api 以编程方式执行相同的操作(但我从未使用过它)。
如果您谈论的是开发数据存储区,您只需删除以下文件:“./WEB-INF/appengine-generated/local_db.bin”。下次您运行开发服务器时,将再次为您生成该文件,您将拥有一个清晰的数据库。
确保之后清理您的项目。
这是您开始使用 Google 应用程序引擎时派上用场的小问题之一。您会发现自己将对象持久化到数据存储中,然后更改可持久化实体的 JDO 对象模型,最终得到过时的数据,这将使您的应用程序到处崩溃。
最好的方法是 Nick 建议的远程 API 方法,他是Google的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,在应用设置中启用它后,您可以通过 web ui 批量删除和备份您的数据存储。
在 Datastore 上处理批量删除的最快、最有效的方法是使用在最新的Google I/O上宣布的新映射器 API。
如果您选择的语言是Python,您只需在mapreduce.yaml文件中注册您的映射器并定义如下函数:
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 开始,有一个用于此目的的数据存储区管理功能
您可以在运行服务器时清除开发服务器数据存储:
/path/to/dev_appserver.py --clear_datastore=yes myapp
您也可以缩写--clear_datastore
为-c
.
如果您有大量数据,则需要使用脚本将其删除。不过,您可以使用 remote_api 以直接的方式从客户端清除数据存储。
开始吧:转到 Datastore Admin,然后选择要删除的实体类型,然后单击删除。Mapreduce 将负责删除!
您可以使用多种方法从 App Engine 的数据存储区中删除条目:
首先,考虑您是否真的需要删除条目。这很昂贵,不移除它们可能更便宜。
您可以使用 Datastore Admin 手动删除所有条目。
您可以使用远程 API 并以交互方式删除条目。
您可以使用几行代码以编程方式删除条目。
您可以使用任务队列和游标批量删除它们。
或者你可以使用 Mapreduce 来获得更强大和更漂亮的东西。
这些方法中的每一种都在以下博客文章中进行了解释:http: //www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore
希望能帮助到你!
执行此操作的零设置方法是将执行任意代码 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())'}))
为您的应用程序打开“Datastore Admin”并启用 Admin。然后您的所有实体都将与复选框一起列出。您可以简单地选择不需要的实体并删除它们。
我创建了一个插件面板,可用于您部署的 App Engine 应用程序。它在下拉列表中列出了数据存储中存在的种类,您可以单击一个按钮来安排“任务”,以删除特定种类的所有实体或简单的所有内容。你可以在这里下载:
http ://code.google.com/p/jobfeed/wiki/Nuke
您可以使用 Web 界面进行操作。登录您的帐户,使用左侧的链接导航。在数据存储管理中,您可以选择修改和删除数据。使用相应的选项。
资源
我从http://code.google.com/appengine/articles/remote_api.html。
创建交互式控制台
首先,您需要定义一个交互式附加控制台。因此,创建一个名为 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 应该只是一个抽象类,它允许您迭代给定类型的每个实体,无论是提取它们的数据,还是修改它们并将更新的实体存储回数据存储区。
带着它跑!
现在,启动您的 appengine 交互式控制台:
$python appengine_console.py <app_id_here>
那应该启动交互式控制台。在其中创建模型的子类:
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()
而已!
这就是你要找的...
db.delete(Entry.all(keys_only=True))
运行仅键查询比完全获取要快得多,并且您的配额将受到较小的影响,因为仅键查询被视为小型操作。
这是尼克约翰逊进一步描述它的答案的链接。
下面是截断表的端到端 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.models 下找到的 Inventory),然后调用 action 参数中指定的正确方法 (Inventory.truncate())。
@basic_auth 是一个装饰器/包装器,它为敏感操作(即 POST/DELETE)提供身份验证。如果您担心安全性,还可以使用oAuth 装饰器。
最后调用动作:
def truncate(self):
db.delete(Inventory.all(keys_only=True))
它看起来像魔术,但实际上非常简单。最好的部分是,delete() 可以通过向模型添加另一个操作来重新用于处理删除一个或多个结果。
对于 Python,1.3.8 包含一个为此内置的实验性管理员。他们说:“在您的 app.yaml 文件中启用以下内置功能:”
builtins:
- datastore_admin: on
“数据存储区删除目前仅适用于 Python 运行时。但是,Java 应用程序仍然可以通过创建一个非默认 Python 应用程序版本来利用此功能,该版本在 app.yaml 中启用数据存储区管理。将包括对 Java 的本机支持在即将发布的版本中。”
您可以通过一一删除所有种类来删除所有数据存储。与谷歌 appengine 仪表板。请按照以下步骤操作。
- 登录https://console.cloud.google.com/datastore/settings
- 单击打开数据存储区管理员。(如果未启用,请启用它。)
- 选择所有实体并按删除。(此步骤运行 map reduce 作业以删除所有选定的种类。)
有关更多信息,请参阅此图片http://storage.googleapis.com/bnifsc/Screenshot%20from%202015-01-31%2023%3A58%3A41.png
添加有关最近发展的答案。
谷歌最近添加了数据存储管理功能。您可以使用此控制台将实体备份、删除或复制到另一个应用程序。
https://developers.google.com/appengine/docs/adminconsole/datastoreadmin#Deleting_Entities_in_Bulk
如果您有大量数据,则使用 Web 界面可能会很耗时。App Engine Launcher实用程序可让您使用“启动时清除数据存储区”复选框一次性删除所有内容。此实用程序现在可用于 Windows 和 Mac(Python 框架)。
对于开发服务器,您可以从终端运行它,而不是通过谷歌应用引擎启动器运行服务器:
dev_appserver.py --port=[端口号] --clear_datastore=yes [应用程序名称]
例如:我的应用程序“reader”在端口 15080 上运行。修改代码并重新启动服务器后,我只运行“dev_appserver.py --port=15080 --clear_datastore=yes reader”。
这对我有好处。
我经常不想删除所有数据存储,所以我将 /war/WEB-INF/local_db.bin 的干净副本拉出源代码控制。可能只是我,但似乎即使在开发模式停止的情况下,我也必须在拉取文件之前物理删除文件。这是在 Windows 上使用 Eclipse 的 subversion 插件。
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 秒。
如果您使用的是 ndb,那么对我来说清除数据存储区的方法:
ndb.delete_multi(ndb.Query(default_options=ndb.QueryOptions(keys_only=True)))
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
我对删除实时数据存储中所有数据的现有解决方案感到非常沮丧,因此我创建了一个小型 GAE 应用程序,该应用程序可以在 30 秒内删除相当多的数据。
对于应用引擎上而不是本地的任何数据存储,您可以使用新的 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()
继续 svpino 的想法,重用标记为删除的记录是明智的。(他的想法不是删除,而是标记为“已删除”未使用的记录)。一点点缓存/内存缓存来处理工作副本并仅将状态差异(在所需任务之前和之后)写入数据存储将使其变得更好。对于大型任务,可以将中间差异块写入数据存储,以避免在 memcache 消失时丢失数据。为了使其防丢失,可以检查 memcached 结果的完整性/存在性并重新启动任务(或所需部分)以重复丢失的计算。当数据差异写入数据存储时,所需的计算将被丢弃在队列中。
与 map reduce 类似的另一个想法是将实体种类分割为几个不同的实体种类,因此它将被收集在一起并作为单个实体种类对最终用户可见。条目仅标记为“已删除”。当每个分片的“已删除”条目数量超过某个限制时,“活动”条目将分布在其他分片之间,并且该分片将永远关闭,然后从开发控制台手动删除(猜测成本更低)更新:控制台似乎没有丢弃表,仅以正常价格逐条删除记录。可以通过查询删除大量记录而不会导致 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;
}
- 有时在主表中创建附加字段而不是将候选人(相关记录)放入单独的表中也很有用。是的,字段可能是未索引/序列化的数组,计算成本很小。
对于所有需要开发服务器快速解决方案的人(截至 2016 年 2 月撰写本文时):
- 停止开发服务器。
- 删除目标目录。
- 重建项目。
这将擦除数据存储中的所有数据。
对于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);
在开发服务器中运行良好
你有2个简单的方法,
#1:为了节省成本,删除整个项目
#2:使用 ts-datastore-orm:
https://www.npmjs.com/package/ts-datastore-orm 等待 Entity.truncate(); 截断可以每秒删除大约 1K 行
以下是我从香草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