Como excluir todo o armazenamento de dados no Google App Engine?

122

Alguém sabe como excluir todos os dados no Google App Engine ?

Dan McGrath
fonte
2
db.delete (db.Query (keys_only = True)). Mais detalhes aqui stackoverflow.com/a/10856555/290340 .
Evan Plaice
4
Conforme apontado pelo @systempuntoout abaixo, o GAE agora possui um administrador de armazenamento de dados que permite excluir entidades em massa sem codificação, entre outras coisas. Esse recurso precisa aparecer aqui em vez de ser enterrado no terceiro comentário.
Ralfoide
O administrador do armazenamento de dados não funciona (a página carrega um iframe em um host inexistente); portanto, ainda precisamos usar o método db.delete.
Para excluir todos os dados no servidor de desenvolvimento, emita o seguinte no prompt do cmd: /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/ onde myappname é o diretório que contém o arquivo app.yaml do aplicativo. Você precisa fazer o cd nesse caminho do diretório. Crédito: Steven Almeroth e Melllvar para obter a resposta abaixo
gsinha

Respostas:

69

Se você estiver falando sobre o armazenamento de dados ao vivo , abra o painel do seu aplicativo (faça login no appengine) e, em seguida, armazenamento de dados -> visualizador de dados, selecione todas as linhas da tabela que deseja excluir e pressione o botão Excluir (você precisará faça isso para todas as suas tabelas). Você pode fazer o mesmo programaticamente através do remote_api (mas nunca o usei).

Se você está falando sobre o armazenamento de dados de desenvolvimento , basta excluir o seguinte arquivo: "./WEB-INF/appengine-generated/local_db.bin" . O arquivo será gerado novamente para você na próxima vez em que executar o servidor de desenvolvimento e você terá um banco de dados limpo.

Certifique-se de limpar seu projeto posteriormente.

Essa é uma das pequenas dicas úteis quando você começa a jogar com o Google Application Engine. Você se encontrará com objetos persistentes no armazenamento de dados e, em seguida, altera o modelo de objeto JDO para suas entidades persistentes, terminando com dados obsoletos que farão com que seu aplicativo falhe por todo o lugar.

JohnIdol
fonte
16
Há um parâmetro -c no dev_appserver.py para excluir do armazenamento de dados de desenvolvimento.
svrist
1
@svrist Mas isso se aplica apenas ao mecanismo de aplicativos Python. Alguém sabe como um atalho para fazê-lo em Java? (Enquanto isso, a sugestão de JohnIdol funciona bem.)
mgiuca
2
Obrigado @John: Onde está o caminho exato no MAC OSX?
George Nguyen
3
Onde está o caminho no Windows?
Shane Best
2
@ShaneBest o caminho em janelas é algo como ./target/yourappid-1.0-SNAPSHOT/WEB-INF/appengine-generated/local_db.bin
morpheus
58

A melhor abordagem é o método de API remota, conforme sugerido por Nick, ele é um engenheiro do Google App Engine , então confie nele.

Não é tão difícil de fazer, e o SDK 1.2.5 mais recente fornece o remote_shell_api.py pronto para uso. Então, faça o download do novo SDK. Em seguida, siga as etapas:

  • conecte o servidor remoto em sua linha de comando: remote_shell_api.py yourapp /remote_api O shell solicitará suas informações de login e, se autorizado, fará um shell Python para você. Você precisa configurar o manipulador de URL para / remote_api no seu app.yaml

  • Para buscar as entidades que você deseja excluir, o código se parece com:

    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

Atualização 2013-10-28 :

  • remote_shell_api.pyfoi substituído por remote_api_shell.pye você deve se conectar com remote_api_shell.py -s your_app_id.appspot.com, de acordo com a documentação .

  • Há um novo recurso experimental Datastore Admin , após ativá-lo nas configurações do aplicativo, você pode excluir em massa e fazer backup do armazenamento de dados pela interface da web.

Juvenn Woo
fonte
17
Na verdade, você não precisa da busca. Apenas db.delete (Entry.all ()) fará isso.
download
4
Você precisa fazer isso em 500 conjuntos de entidades ou poderá obter: BadRequestError: não é possível excluir mais de 500 entidades em uma única chamada
marcc
1
Apenas um FYI, para você usar a API remota, você precisa habilitá-la no seu aplicativo primeiro usando builtins: - remote_api: no seu arquivo YAML. mais informações estão em developers.google.com/appengine/articles/remote_api
Zaffiro
2
Adicione pelo menos o 'keys_only = True' quando você chamar Entry.all (). Não é necessário buscar a entrada inteira se você não precisar verificar os dados. Caso contrário, você está apenas desperdiçando ciclos de computação.
Evan Plaice
1
+1 ... mas: a partir de 2013, remote_shell_api.py não existe. O nome do script atual é remote_api_shell.py. Além disso, se você usar o NDB (que é o que a maioria das pessoas nos dias de hoje), forma recomendada para uso ndb.delete_multi (. Model.Entry.query () fetch (keys_only = True))
Uri
27

A maneira mais rápida e eficiente de lidar com a exclusão em massa no Datastore é usando a nova API do mapeador anunciada na mais recente E / S do Google .

Se sua linguagem de escolha for Python , você apenas precisará registrar seu mapeador em um arquivo mapreduce.yaml e definir uma função como esta:

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

Em Java, você deve dar uma olhada neste artigo que sugere uma função como esta:

@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());
}

EDIT:
Desde o SDK 1.3.8, há um recurso de administrador do Datastore para essa finalidade

systempuntoout
fonte
27

Você pode limpar o armazenamento de dados do servidor de desenvolvimento ao executar o servidor:

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

Você também pode abreviar --clear_datastorecom -c.

Steven Almeroth
fonte
5
Não tenho certeza se é uma coisa recente, mas a sintaxe real é agora /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/(note o 'sim')
Melllvar
É a maneira mais útil de excluir repetidamente o armazenamento de dados durante o desenvolvimento. Com opções de obtenção rápida obsoleto, que vale a pena destacar esta bandeira ainda está em vigor em julho de 2018, e trabalha para dev_appserver instalado via CLI gcloud
Michael
Na versão 270.0.0 do Google Cloud SDK "--clear_datastore = yes" ainda funciona com o sinal de igual
franksands
15

Se você tiver uma quantidade significativa de dados, precisará usar um script para excluí-lo. Você pode usar remote_api para limpar o armazenamento de dados do lado do cliente de maneira direta.

Nick Johnson
fonte
11

Aqui você vai: Vá para Admin do armazenamento de dados e selecione o tipo de entidade que deseja excluir e clique em Excluir. Mapreduce cuidará da exclusão!

David
fonte
9

Existem várias maneiras de remover as entradas do armazenamento de dados do App Engine:

insira a descrição da imagem aqui

  1. Primeiro, pense se você realmente precisa remover as entradas. Isso é caro e pode ser mais barato não removê-los.

  2. Você pode excluir todas as entradas manualmente usando o administrador do armazenamento de dados.

  3. Você pode usar a API remota e remover entradas interativamente.

  4. Você pode remover as entradas programaticamente usando algumas linhas de código.

  5. Você pode removê-los em massa usando as Filas de tarefas e os Cursores.

  6. Ou você pode usar o Mapreduce para obter algo mais robusto e sofisticado.

Cada um desses métodos é explicado na seguinte postagem no blog: http://www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore

Espero que ajude!

svpino
fonte
6

A maneira de configuração zero para fazer isso é enviar uma solicitação HTTP de código arbitrário de execução para o serviço de administração que seu aplicativo em execução já possui automaticamente:

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())'}))
dfichter
fonte
Isso funciona apenas para o servidor de desenvolvimento. Existe um equivalente de produção?
Gady
3

Fonte

Eu peguei isso de http://code.google.com/appengine/articles/remote_api.html .

Crie o console interativo

Primeiro, você precisa definir um console de aplicativo interativo. Portanto, crie um arquivo chamado appengine_console.py e digite o seguinte:

#!/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())



Crie a classe base do Mapper

Uma vez instalado, crie essa classe Mapper. Acabei de criar um novo arquivo chamado utils.py e joguei isso:

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)

Supõe-se que o Mapper seja apenas uma classe abstrata que permite iterar todas as entidades de um determinado tipo, seja para extrair seus dados ou modificá-los e modificá-los e armazenar as entidades atualizadas no armazenamento de dados.

Corra com ele!

Agora, inicie o console interativo do mecanismo de aplicativos:

$python appengine_console.py <app_id_here>

Isso deve iniciar o console interativo. Nele, crie uma subclasse de Model:

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

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

E, finalmente, execute-o (no seu console interativo): mapper = MyModelDeleter () mapper.run ()

É isso aí!

Gezim
fonte
3

Você pode fazer isso usando a interface da web. Entre na sua conta, navegue com links no lado esquerdo. No gerenciamento de armazenamento de dados, você tem opções para modificar e excluir dados. Use as opções respectivas.

Priyank
fonte
3

Criei um painel de suplemento que pode ser usado com seus aplicativos implantados do App Engine. Ele lista os tipos presentes no armazenamento de dados em uma lista suspensa e você pode clicar em um botão para agendar "tarefas" que excluem todas as entidades de um tipo específico ou simplesmente tudo. Você pode fazer o download aqui:
http://code.google.com/p/jobfeed/wiki/Nuke

kostmo
fonte
3

Para Python, 1.3.8 inclui um administrador experimental embutido para isso. Eles dizem : "habilite o seguinte componente no arquivo app.yaml:"

builtins:
- datastore_admin: on

"No momento, a exclusão do armazenamento de dados está disponível apenas com o tempo de execução do Python. Os aplicativos Java, no entanto, ainda podem tirar proveito desse recurso criando uma versão do aplicativo Python não padrão que permite o administrador do armazenamento de dados no app.yaml. Suporte nativo para Java será incluído em um próximo lançamento ".

dfrankow
fonte
A adição da configuração no app.yaml gerou um erro. Em vez disso, podemos ativá-lo na página 'Configuração de aplicativos' na seção 'Administração'. Há um botão para ativá-lo
Sundeep
3

Abra "Admin do armazenamento de dados" para seu aplicativo e ative Admin. Todas as suas entidades serão listadas com caixas de seleção. Você pode simplesmente selecionar as entidades indesejadas e excluí-las.

Girish007
fonte
3

Isto é o que você está procurando ...

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

A execução de uma consulta apenas de chaves é muito mais rápida que uma busca completa, e sua cota sofrerá um impacto menor porque as consultas apenas de chaves são consideradas pequenas operações.

Aqui está um link para uma resposta de Nick Johnson descrevendo-a ainda mais.

Abaixo está uma solução de API REST de ponta a ponta para truncar uma tabela ...

Eu configurei uma API REST para lidar com transações de banco de dados nas quais as rotas são mapeadas diretamente no modelo / ação apropriado. Isso pode ser chamado digitando o URL correto (exemplo.com/inventory/truncate) e fazendo login.

Aqui está a rota:

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

Aqui está o manipulador:

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

Começa carregando o modelo dinamicamente (ou seja, Inventário encontrado em api.models) e depois chama o método correto (Inventory.truncate ()) conforme especificado no parâmetro de ação.

O @basic_auth é um decorador / wrapper que fornece autenticação para operações confidenciais (ou seja, POST / DELETE). Há também um decorador oAuth disponível se você estiver preocupado com a segurança.

Finalmente, a ação é chamada:

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

Parece mágica, mas na verdade é muito direta. A melhor parte é que delete () pode ser reutilizado para lidar com a exclusão de um ou muitos resultados, adicionando outra ação ao modelo.

Evan Plaice
fonte
3

Você pode excluir todo o armazenamento de dados excluindo todos os tipos, um por um. com o painel de instrumentos do google appengine. Por favor, siga estes passos.

  1. Faça login em https://console.cloud.google.com/datastore/settings
  2. Clique em Abrir administrador do armazenamento de dados . (Ative se não estiver ativado.)
  3. Selecione todas as entidades e pressione Excluir. (Esta etapa executa um trabalho de redução de mapa para excluir todos os tipos selecionados.)

para obter mais informações, consulte esta imagem http://storage.googleapis.com/bnifsc/Screenshot%20from%202015-01-31%2023%3A58%3A41.png

vinay mavi
fonte
2

Se você possui muitos dados, o uso da interface da web pode levar muito tempo. O utilitário Iniciador do App Engine permite excluir tudo de uma só vez com a caixa de seleção 'Limpar armazenamento de dados ao iniciar'. Este utilitário agora está disponível para Windows e Mac (estrutura Python).

lucrussell
fonte
2

Para o servidor de desenvolvimento, em vez de executar o servidor por meio do iniciador do mecanismo de aplicativos do Google, você pode executá-lo a partir do terminal, como:

dev_appserver.py --port = [número da porta] --clear_datastore = yes [nameofapplication]

ex: meu aplicativo "reader" roda na porta 15080. Após modificar o código e reiniciar o servidor, executei "dev_appserver.py --port = 15080 --clear_datastore = yes reader".

É bom para mim.

user1552891
fonte
1

Geralmente, não quero excluir todo o armazenamento de dados, por isso retiro uma cópia limpa do /war/WEB-INF/local_db.bin para fora do controle de origem. Pode ser apenas eu, mas parece que mesmo com o Modo Dev parado eu tenho que remover fisicamente o arquivo antes de puxá-lo. Isso está no Windows usando o plug-in subversion para Eclipse.

Dominic
fonte
0

Variação do 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);
        }
    }
}

Sim, isso levará tempo e 30 segundos. é um limite. Estou pensando em colocar um exemplo de aplicativo ajax para automatizar além de 30 segundos.

MarkokraM
fonte
Isso nem é php válido. import? Definindo uma constante como uma instância de objeto?
23416 Josh J
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
JQuery Guru
fonte
0

Se você estiver usando o ndb, o método que funcionou para mim para limpar o armazenamento de dados:

ndb.delete_multi(ndb.Query(default_options=ndb.QueryOptions(keys_only=True)))
Gilad Beeri
fonte
1
Eu não acho que isso vai funcionar. Appengine reclama Sorry, unexpected error: The kind "__Stat_Kind__" is reserved.Esta parece ser appengine tem alguma entidade estatísticas interna que pode ser exposta por este método (possível bug em sua extremidade?)
disappearedng
0

Para qualquer armazenamento de dados que esteja no mecanismo de aplicativos, e não local, você pode usar a nova API do armazenamento de dados . Aqui está uma cartilha de como começar .

Eu escrevi um script que exclui todas as entidades não criadas. A API está mudando rapidamente, portanto, para referência, eu a clonei em commit 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 = '[email protected]'
  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()
Yonatan Kogan
fonte
0
  • continuando a idéia do svpino, é prudente reutilizar os registros marcados como delete. (a ideia dele era não remover, mas marcar como "excluídos" registros não utilizados). um pouco de cache / memcache para lidar com a cópia de trabalho e gravar apenas a diferença de estados (antes e depois da tarefa desejada) no armazenamento de dados o tornará melhor. para grandes tarefas, é possível gravar blocos de diferença iterados no armazenamento de dados para evitar a perda de dados se o memcache desaparecer. para torná-lo à prova de perda, é possível verificar a integridade / existência de resultados armazenados em cache e reiniciar a tarefa (ou parte necessária) para repetir os cálculos ausentes. quando a diferença de dados é gravada no armazenamento de dados, os cálculos necessários são descartados na fila.

  • outra idéia semelhante ao mapa reduzido é dividir o tipo de entidade para vários tipos de entidades diferentes, para que seja coletado em conjunto e visível como tipo de entidade única para o usuário final. as entradas são marcadas apenas como "excluídas". quando "excluído" entradas valor por caco supera algum limite, as entradas "vivos" são distribuídos entre os outros fragmentos, e este fragmento está fechado para sempre e, em seguida, excluído manualmente do dev console (adivinhar a um custo menor) UPD: parece nenhuma tabela queda no console, exclua apenas registro por registro a preço normal.

  • é possível excluir por consulta por blocos grandes conjuntos de registros sem gae falhar (pelo menos funciona localmente) com possibilidade de continuar na próxima tentativa quando o tempo acabar:


    qdelete.getFetchPlan().setFetchSize(100);

    while (true)
    {
        long result = qdelete.deletePersistentAll(candidates);
        LOG.log(Level.INFO, String.format("deleted: %d", result));
        if (result <= 0)
            break;
    }
  • às vezes, também é útil criar um campo adicional na tabela primária em vez de colocar candidatos (registros relacionados) em uma tabela separada. e sim, o campo pode ser um array não indexado / serializado com pouco custo de computação.
Dmitry Bryliuk
fonte
0

Para todas as pessoas que precisam de uma solução rápida para o servidor de desenvolvimento (como o tempo de escrita em fevereiro de 2016):

  1. Pare o servidor de desenvolvimento.
  2. Exclua o diretório de destino .
  3. Reconstrua o projeto.

Isso limpará todos os dados do armazenamento de dados.

alexanderb14
fonte
0

Fiquei tão frustrado com as soluções existentes para excluir todos os dados no armazenamento de dados ao vivo que criei um pequeno aplicativo GAE que pode excluir uma quantidade considerável de dados em seus 30 segundos.

Como instalar etc: https://github.com/xamde/xydra

Dr. Max Völkel
fonte
0

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

Funciona bem no Development Server

Prakash Ayappan
fonte
0

Você tem 2 maneiras simples,

# 1: para economizar custos, exclua todo o projeto

# 2: usando ts-datastore-orm:

https://www.npmjs.com/package/ts-datastore-orm aguardam Entity.truncate (); O truncado pode excluir cerca de 1 mil linhas por segundo

Tsang Kin Ho
fonte