Come eliminare tutto il datastore in Google App Engine?


122

Qualcuno sa come eliminare tutto il datastore in Google App Engine ?


2
db.delete (db.Query (keys_only = True)). Ulteriori dettagli qui stackoverflow.com/a/10856555/290340 .
Evan Plaice

4
Come sottolineato da @systempuntoout di seguito, GAE ora ha un amministratore di Datastore che ti consente di eliminare le entità in blocco senza alcuna codifica, tra le altre cose. Quella caratteristica deve essere emersa qui piuttosto che sepolta nel terzo commento.
ralfoide

L'amministratore di Datastore non funziona (la pagina carica un iframe su un host inesistente), quindi avremmo ancora bisogno di utilizzare il metodo db.delete.

Per eliminare tutti i dati sul server di sviluppo, emettere quanto segue al prompt di cmd: /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/ dove myappname è la directory contenente il file app.yaml per l'app .. è necessario eseguire il cd in questo percorso di directory .. credito: Steven Almeroth e Melllvar per la risposta di seguito
gsinha

Risposte:


69

Se stai parlando del datastore live , apri la dashboard per la tua app (accedi ad appengine) quindi datastore -> dataviewer, seleziona tutte le righe per la tabella che desideri eliminare e premi il pulsante Elimina (dovrai fallo per tutte le tue tabelle). Puoi fare lo stesso a livello di programmazione tramite remote_api (ma non l'ho mai usato).

Se stai parlando del datastore di sviluppo , devi solo eliminare il seguente file: "./WEB-INF/appengine-generated/local_db.bin" . Il file verrà generato nuovamente per te la prossima volta che esegui il server di sviluppo e avrai un db chiaro.

Assicurati di pulire il tuo progetto in seguito.

Questo è uno dei piccoli trucchi che tornano utili quando inizi a giocare con Google Application Engine. Ti ritroverai a persistere oggetti nel datastore, quindi a modificare il modello di oggetti JDO per le tue entità persistenti finendo con dati obsoleti che faranno crashare la tua app ovunque.


16
C'è un parametro -c per dev_appserver.py da eliminare dal datastore di sviluppo.
svrist

1
@svrist Ma questo vale solo per il motore delle app Python. Qualcuno sa come una scorciatoia per farlo in Java? (Nel frattempo, il suggerimento di JohnIdol funziona bene.)
mgiuca

2
Grazie @ John: dov'è il percorso esatto in MAC OSX?
George Nguyen

3
Dov'è il percorso in Windows?
Shane Best

2
@ShaneBest il percorso in Windows è qualcosa come ./target/yourappid-1.0-SNAPSHOT/WEB-INF/appengine-generated/local_db.bin
morpheus

58

L'approccio migliore è il metodo API remoto come suggerito da Nick, è un ingegnere di App Engine di Google , quindi fidati di lui.

Non è così difficile da fare e l'ultimo SDK 1.2.5 fornisce remote_shell_api.py immediatamente. Quindi vai a scaricare il nuovo SDK. Quindi segui i passaggi:

  • connetti il ​​server remoto nella tua riga di comando: remote_shell_api.py yourapp /remote_api La shell chiederà le tue informazioni di accesso e, se autorizzato, creerà una shell Python per te. Devi impostare il gestore dell'URL per / remote_api nel tuo app.yaml

  • recupera le entità che desideri eliminare, il codice ha un aspetto simile a:

    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

Aggiornamento 2013-10-28 :

  • remote_shell_api.pyè stato sostituito da remote_api_shell.py, e dovresti connetterti con remote_api_shell.py -s your_app_id.appspot.com, secondo la documentazione .

  • È disponibile una nuova funzionalità sperimentale Datastore Admin , dopo averla abilitata nelle impostazioni dell'app, è possibile eliminare in blocco e eseguire il backup del datastore tramite l'interfaccia utente web.


17
In realtà, non hai bisogno del recupero. Solo db.delete (Entry.all ()) lo farà.
scarica il

4
Devi farlo in 500 set di entità altrimenti otterrai: BadRequestError: impossibile eliminare più di 500 entità in una singola chiamata
marcc

1
Per tua informazione, per poter utilizzare l'API remota devi prima abilitarlo nella tua applicazione usando i builtin: - remote_api: nel tuo file YAML. maggiori informazioni sono su developers.google.com/appengine/articles/remote_api
Zaffiro

2
Almeno aggiungi "keys_only = True" quando chiami Entry.all (). Non è necessario recuperare l'intera voce se non è necessario controllare i dati. Altrimenti stai solo sprecando cicli di elaborazione.
Evan Plaice,

1
+1 ... ma: dal 2013, remote_shell_api.py non esiste. Il nome dello script corrente è remote_api_shell.py. Inoltre, se usi ndb (che è quello che fa la maggior parte delle persone in questi giorni), metodo consigliato per usare ndb.delete_multi (model.Entry.query (). Fetch (keys_only = True))
Uri

27

Il modo più veloce ed efficiente per gestire l'eliminazione in blocco su Datastore è utilizzare la nuova API mapper annunciata nell'ultimo I / O di Google .

Se la tua lingua preferita è Python , devi solo registrare il tuo mappatore in un file mapreduce.yaml e definire una funzione come questa:

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

Su Java dovresti dare un'occhiata a questo articolo che suggerisce una funzione come questa:

@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: a
partire dall'SDK 1.3.8, c'è una funzionalità di amministrazione di Datastore per questo scopo


27

È possibile cancellare il datastore del server di sviluppo quando si esegue il server:

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

Puoi anche abbreviare --clear_datastorecon -c.


5
Non sono sicuro che sia una cosa recente, ma la sintassi effettiva è adesso /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/(nota il "sì")
Melllvar

È il modo più utile per eliminare ripetutamente il datastore durante lo sviluppo. Con le opzioni che diventano rapidamente obsolete, vale la pena evidenziare che questo flag è ancora in vigore a luglio 2018 e funziona per dev_appserver installato tramite gcloud CLI
Michael

Nella versione 270.0.0 di Google Cloud SDK "--clear_datastore = yes" funziona ancora con il segno di uguale
franksands,

15

Se si dispone di una quantità significativa di dati, è necessario utilizzare uno script per eliminarli. Tuttavia, puoi utilizzare remote_api per cancellare il datastore dal lato client in modo semplice.


11

Ecco fatto: vai su Datastore Admin, quindi seleziona il tipo di entità che desideri eliminare e fai clic su Elimina. Mapreduce si occuperà dell'eliminazione!


9

Esistono diversi modi per rimuovere le voci dal datastore di App Engine:

inserisci qui la descrizione dell'immagine

  1. Innanzitutto, pensa se hai davvero bisogno di rimuovere le voci. Questo è costoso e potrebbe essere più economico non rimuoverli.

  2. È possibile eliminare manualmente tutte le voci utilizzando Datastore Admin.

  3. È possibile utilizzare l'API remota e rimuovere le voci in modo interattivo.

  4. È possibile rimuovere le voci a livello di codice utilizzando un paio di righe di codice.

  5. Puoi rimuoverli in blocco utilizzando le code di attività ei cursori.

  6. Oppure puoi usare Mapreduce per ottenere qualcosa di più robusto e più elaborato.

Ciascuno di questi metodi è spiegato nel seguente post del blog: http://www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore

Spero che sia d'aiuto!


6

Il modo di configurazione zero per farlo è inviare una richiesta HTTP di codice arbitrario di esecuzione al servizio di amministrazione che l'app in esecuzione ha già, 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())'}))

Funziona solo per il server di sviluppo. Esiste un equivalente di produzione?
Gady

3

fonte

L'ho preso da http://code.google.com/appengine/articles/remote_api.html .

Crea la console interattiva

Innanzitutto, è necessario definire una console di appenginge interattiva. Quindi, crea un file chiamato appengine_console.py e inserisci questo:

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



Crea la classe base Mapper

Una volta che è a posto, crea questa classe Mapper. Ho appena creato un nuovo file chiamato utils.py e ho lanciato questo:

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 dovrebbe essere solo una classe astratta che ti consente di iterare su ogni entità di un determinato tipo, sia per estrarre i loro dati, sia per modificarli e memorizzare le entità aggiornate nel datastore.

Corri con esso!

Ora avvia la tua console interattiva appengine:

$python appengine_console.py <app_id_here>

Questo dovrebbe avviare la console interattiva. In esso crea una sottoclasse di Model:

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

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

E, infine, eseguilo (dalla tua console interattiva): mapper = MyModelDeleter () mapper.run ()

Questo è tutto!


3

Puoi farlo usando l'interfaccia web. Accedi al tuo account, naviga con i link sul lato sinistro. Nella gestione dell'archivio dati sono disponibili opzioni per modificare ed eliminare i dati. Usa le rispettive opzioni.


3

Ho creato un pannello aggiuntivo che può essere utilizzato con le tue app App Engine distribuite. Elenca i tipi presenti nel datastore in un menu a discesa e puoi fare clic su un pulsante per pianificare "attività" che eliminano tutte le entità di un tipo specifico o semplicemente tutto. Puoi scaricarlo qui:
http://code.google.com/p/jobfeed/wiki/Nuke


3

Per Python, 1.3.8 include un admin sperimentale integrato per questo. Essi dicono : "abilitare il seguente incorporato nel file app.yaml:"

builtins:
- datastore_admin: on

"L'eliminazione del datastore è attualmente disponibile solo con il runtime Python. Le applicazioni Java, tuttavia, possono ancora trarre vantaggio da questa funzionalità creando una versione dell'applicazione Python non predefinita che abilita l'amministratore del datastore in app.yaml. Sarà incluso il supporto nativo per Java in una delle prossime versioni. "


L'aggiunta della configurazione in app.yaml ha generato un errore. Invece possiamo abilitarlo dalla pagina "Impostazioni applicazioni" nella sezione "Amministrazione". C'è un pulsante per abilitarlo
Sundeep

3

Apri "Datastore Admin" per la tua applicazione e abilita Admin. Quindi tutte le tue entità verranno elencate con caselle di controllo. Puoi semplicemente selezionare le entite indesiderate ed eliminarle.


3

Questo è quello che stai cercando ...

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

L'esecuzione di una query solo chiavi è molto più veloce di un recupero completo e la tua quota avrà un colpo minore perché le query solo chiavi sono considerate operazioni di piccole dimensioni.

Ecco un collegamento a una risposta di Nick Johnson che lo descrive ulteriormente.

Di seguito è una soluzione API REST end-to-end per troncare una tabella ...

Ho impostato un'API REST per gestire le transazioni del database in cui le rotte vengono mappate direttamente al modello / azione appropriato. Questo può essere chiamato inserendo l'URL corretto (example.com/inventory/truncate) e accedendo.

Ecco il percorso:

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

Ecco il gestore:

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

Inizia caricando il modello dinamicamente (cioè Inventory trovato sotto api.models), quindi chiama il metodo corretto (Inventory.truncate ()) come specificato nel parametro action.

@Basic_auth è un decoratore / wrapper che fornisce l'autenticazione per operazioni sensibili (es. POST / DELETE). C'è anche un decoratore oAuth disponibile se sei preoccupato per la sicurezza.

Infine, l'azione si chiama:

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

Sembra magico ma in realtà è molto semplice. La parte migliore è che delete () può essere riutilizzato per gestire l'eliminazione di uno o più risultati aggiungendo un'altra azione al modello.


3

È possibile eliminare tutti i datastore eliminando tutti i tipi uno per uno. con cruscotto google appengine. Si prega di seguire questi passaggi.

  1. Accedi a https://console.cloud.google.com/datastore/settings
  2. Fare clic su Apri amministrazione datastore . (Abilitalo se non abilitato.)
  3. Seleziona tutte le entità e premi Elimina (in questo passaggio viene eseguito un lavoro di riduzione della mappa per eliminare tutti i tipi selezionati).

per maggiori informazioni vedi questa immagine http://storage.googleapis.com/bnifsc/Screenshot%20from%202015-01-31%2023%3A58%3A41.png


2

Se si dispone di molti dati, l'utilizzo dell'interfaccia Web potrebbe richiedere molto tempo. L' utilità di avvio di App Engine ti consente di eliminare tutto in una volta sola con la casella di controllo "Cancella archivio dati all'avvio". Questa utility è ora disponibile sia per Windows che per Mac (framework Python).


2

Per il server di sviluppo, invece di eseguire il server tramite il programma di avvio del motore di app di Google, puoi eseguirlo dal terminale come:

dev_appserver.py --port = [portnumber] --clear_datastore = yes [nameofapplication]

es: la mia applicazione "reader" gira sulla porta 15080. Dopo aver modificato il codice e riavviato il server, eseguo semplicemente "dev_appserver.py --port = 15080 --clear_datastore = yes reader".

Va bene per me.



1

Spesso non voglio eliminare tutto l'archivio dati, quindi eseguo una copia pulita di /war/WEB-INF/local_db.bin dal controllo del codice sorgente. Potrei essere solo io, ma sembra che anche con la modalità Dev interrotta devo rimuovere fisicamente il file prima di estrarlo. Questo è su Windows utilizzando il plugin subversion per Eclipse.


0

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

Sì, ci vorrà tempo e 30 sec. è un limite. Sto pensando di mettere un esempio di app ajax per automatizzare oltre 30 sec.


Questo non è nemmeno un php valido. import? Definizione di una costante come istanza di un oggetto?
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

0

Se stai usando ndb, il metodo che ha funzionato per me per cancellare il datastore:

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

1
Non credo che funzionerà. Appengine si lamenta Sorry, unexpected error: The kind "__Stat_Kind__" is reserved.Sembra che appengine abbia un'entità statistica interna che può essere esposta con questo metodo (possibile bug alla fine?)
scomparso l'

0

Per qualsiasi archivio dati presente sul motore dell'app, anziché locale, puoi utilizzare la nuova API Datastore . Ecco un primer su come iniziare .

Ho scritto uno script che elimina tutte le entità non integrate. L'API sta cambiando abbastanza rapidamente, quindi per riferimento, l'ho clonato su 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 = '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()

0
  • continuando l'idea di svpino è opportuno riutilizzare i record contrassegnati come cancellati. (La sua idea non era quella di rimuovere, ma contrassegnare come "cancellati" i record inutilizzati). un po 'di cache / memcache per gestire la copia di lavoro e scrivere solo la differenza di stati (prima e dopo l'attività desiderata) nel datastore lo renderà migliore. per i compiti più grandi è possibile scrivere frammenti di differenze intermedie nel datastore per evitare la perdita di dati se memcache scompare. per renderlo a prova di perdita è possibile verificare l'integrità / l'esistenza dei risultati di memcached e riavviare l'attività (o la parte richiesta) per ripetere i calcoli mancanti. quando la differenza di dati viene scritta nel datastore, i calcoli richiesti vengono scartati in coda.

  • un'altra idea simile alla mappa ridotta è quella di suddividere il tipo di entità in diversi tipi di entità differenti, quindi sarà raccolta insieme e visibile come singolo tipo di entità all'utente finale. le voci sono contrassegnate solo come "cancellate". quando la quantità di voci "cancellate" per frammento supera un certo limite, le voci "vive" vengono distribuite tra altri frammenti, e questo frammento viene chiuso per sempre e quindi eliminato manualmente dalla console di sviluppo (ipotesi a un costo inferiore) . elimina solo record per record a prezzo normale.

  • è possibile eliminare tramite query per blocchi un insieme di record di grandi dimensioni senza che gae fallisca (almeno funziona localmente) con la possibilità di continuare nel tentativo successivo quando il tempo è finito:


    qdelete.getFetchPlan().setFetchSize(100);

    while (true)
    {
        long result = qdelete.deletePersistentAll(candidates);
        LOG.log(Level.INFO, String.format("deleted: %d", result));
        if (result <= 0)
            break;
    }
  • inoltre a volte è utile creare un campo aggiuntivo nella tabella primaria invece di inserire i candidati (record correlati) in una tabella separata. e sì, il campo può essere un array non indicizzato / serializzato con un costo di calcolo ridotto.

0

Per tutte le persone che necessitano di una soluzione rapida per il server di sviluppo (al momento della scrittura di febbraio 2016):

  1. Arresta il server di sviluppo.
  2. Elimina la directory di destinazione .
  3. Ricostruisci il progetto.

Questo cancellerà tutti i dati dal datastore.


0

Ero così frustrato dalle soluzioni esistenti per l' eliminazione di tutti i dati nel datastore live che ho creato una piccola app GAE che può eliminare una certa quantità di dati entro i suoi 30 secondi.

Come installare ecc: https://github.com/xamde/xydra


0

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

Funziona bene in Development Server


Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.