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

3

这就是你要找的东西...

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

运行一个仅针对键的查询比完整获取要快得多,因为只针对键的查询被认为是小型操作,所以你的配额会受到较小的影响。
这里有一个来自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.models下找到的Inventory),然后根据action参数调用正确的方法(Inventory.truncate())。

@basic_auth是一个装饰器/封装器,为敏感操作(例如POST/DELETE)提供身份验证。如果您关心安全性,则还有一个oAuth装饰器可用。

最后,调用action:

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

看起来像魔法,但实际上非常简单。最好的部分是,delete()可以被重复使用,通过向模型添加另一个操作来处理删除一个或多个结果。


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

3
您可以通过逐个删除所有种类来删除所有数据存储。使用Google App Engine控制面板,请按照以下步骤操作:
  1. 登录https://console.cloud.google.com/datastore/settings
  2. 单击打开Datastore Admin。(如果未启用,请启用它)
  3. 选择所有实体并按删除键。(此步骤运行一个MapReduce作业以删除所有选定的种类。)

有关更多信息,请参见此图片:http://storage.googleapis.com/bnifsc/Screenshot%20from%202015-01-31%2023%3A58%3A41.png


请注意,您所附加的图像权限被拒绝。此外,这是针对“Datastore模式下的Firestore”还是旧版的“Datastore”产品,该产品现已迁移到Firestore? - OscarVanL

3

您可以使用Web界面完成此操作。登录您的账户,在左侧链接中导航。在数据存储管理中,您有修改和删除数据的选项。使用相应的选项。


3
打开应用程序的“数据存储管理器”,并启用管理员权限。然后所有实体将以复选框的形式列出。您只需选择不需要的实体并删除即可。

2

对于开发服务器,不要通过Google应用引擎启动器运行服务器,而是可以从终端运行:

dev_appserver.py --port=[端口号] --clear_datastore=yes [应用程序名称]

例如:我的应用程序“reader”在15080端口上运行。修改代码并重新启动服务器后,我只需运行“dev_appserver.py --port=15080 --clear_datastore=yes reader”。

这对我很有帮助。


2

如果你有大量的数据,使用网页界面可能会耗费很多时间。使用App Engine Launcher工具可以通过“Clear datastore on launch”复选框一次性删除所有内容。该工具现已适用于Windows和Mac(Python框架)。


2

1
截至2022年,据我所知,有两种方法可以从(相对较大的)数据存储中删除一种kind。Google建议使用Dataflow模板。该模板基本上会依据GQL查询逐个拉取每个实体,然后将其删除。有趣的是,如果您要删除大量数据行(> 10m),则会遇到数据存储问题;因为它将无法提供足够的容量,而且您对数据存储的操作将开始超时。但是,只有您正在批量删除的kind会受到影响。
如果您的数据行少于10m,则可以使用此Go脚本:
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))
}

1

我经常不想删除所有数据存储,所以我从源代码控制中拉出 /war/WEB-INF/local_db.bin 的干净副本。也许只有我这样,但即使停止 Dev Mode,我似乎仍然需要在拉取之前物理删除该文件。这是在 Windows 上使用 Eclipse 的 Subversion 插件。


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