web-dev-qa-db-fra.com

Comment supprimer tous les magasins de données dans Google App Engine?

Quelqu'un sait-il comment supprimer tous les magasins de données de Google App Engine ?

122
manman

Si vous parlez du magasin de données en direct , ouvrez le tableau de bord de votre application (connexion sur un moteur), puis magasin de données -> gestionnaire de données, sélectionnez toutes les lignes. pour la table que vous souhaitez supprimer et appuyez sur le bouton Supprimer (vous devrez le faire pour toutes vos tables). Vous pouvez faire la même chose par programme via remote_api (mais je ne l'ai jamais utilisé).

Si vous parlez de magasin de données de développement, il vous suffira de supprimer le fichier suivant: "./ WEB-INF/généré par appengine/local_db.bin" . Le fichier sera généré à nouveau pour vous la prochaine fois que vous exécuterez le serveur de développement et vous aurez une base de données claire.

Assurez-vous de nettoyer votre projet après.

C’est l’un des petits pièges qui vous sera utile lorsque vous commencerez à jouer avec Google Application Engine. Vous vous retrouvez avec des objets persistants dans le magasin de données, puis vous modifiez le modèle d'objet JDO pour vos entités persistantes, ce qui aboutit à des données obsolètes qui feront planter votre application dans tous les sens.

69
JohnIdol

La meilleure approche est la méthode de l’API distante suggérée par Nick; il est un ingénieur App Engine de Google , alors faites-lui confiance.

Ce n'est pas si difficile à faire, et le dernier SDK 1.2.5 fournit le fichier remote_Shell_api.py en vente libre. Allez donc télécharger le nouveau SDK. Puis suivez les étapes:

  • connectez le serveur distant dans votre ligne de commande: remote_Shell_api.py yourapp /remote_api Le shell vous demandera vos informations de connexion et, s’il y est autorisé, créera un shell Python). Vous avez besoin du gestionnaire d’URL d’installation pour/remote_api dans votre app.yaml.

  • chercher les entités que vous souhaitez supprimer, le code ressemble à quelque chose comme:

    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

Mise à jour 2013-10-28 :

  • remote_Shell_api.py a été remplacé par remote_api_Shell.py, et vous devriez vous connecter avec remote_api_Shell.py -s your_app_id.appspot.com, selon la documentation .

  • Il existe une nouvelle fonctionnalité expérimentale Administrateur de magasin de données . Après l'avoir activée dans les paramètres de l'application, vous pouvez supprimer en bloc ainsi que sauvegarder votre magasin de données via l'interface Web.

58
Juvenn Woo

Le moyen le plus rapide et le plus efficace de gérer la suppression en bloc sur le magasin de données consiste à utiliser le nouveau mapper API annoncé sur le dernier (Google I/O .

Si votre langue de choix est Python , il vous suffit d'enregistrer votre mappeur dans un fichier mapreduce.yaml et de définir une fonction comme celle-ci:

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

Sur Java , vous devriez jeter un oeil sur cet article qui suggère une fonction comme celle-ci:

@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:
Depuis le SDK 1.3.8, il existe un fonction d’administrateur de magasin de données à cet effet

27
systempuntoout

Vous pouvez effacer le magasin de données du serveur de développement lorsque vous exécutez le serveur:

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

Vous pouvez aussi abréger --clear_datastore avec -c.

26
Steven Almeroth

Si vous avez une quantité importante de données, vous devez utiliser un script pour les supprimer. Vous pouvez utiliser remote_api pour effacer le magasin de données du côté client de manière simple.

15
Nick Johnson

Ici vous allez: Allez dans Datastore Admin, puis sélectionnez le type d'entité que vous voulez supprimer et cliquez sur Supprimer. Mapreduce se chargera de supprimer!

11
David

Vous pouvez utiliser plusieurs méthodes pour supprimer des entrées du magasin de données d'App Engine:

enter image description here

  1. Commencez par déterminer si vous devez vraiment supprimer des entrées. Cela coûte cher et il pourrait être moins coûteux de ne pas les supprimer.

  2. Vous pouvez supprimer toutes les entrées manuellement à l'aide de l'administrateur de magasin de données.

  3. Vous pouvez utiliser l'API à distance et supprimer des entrées de manière interactive.

  4. Vous pouvez supprimer les entrées par programme en utilisant quelques lignes de code.

  5. Vous pouvez les supprimer en bloc à l'aide des files d'attente et des curseurs.

  6. Ou vous pouvez utiliser Mapreduce pour obtenir quelque chose de plus robuste et plus sophistiqué.

Chacune de ces méthodes est expliquée dans le blog suivant: http://www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore

J'espère que ça aide!

9
svpino

Pour ce faire, la méthode la plus simple consiste à envoyer une demande HTTP à code exécutable à code arbitraire au service d'administration que votre application en cours d'exécution a déjà automatiquement:

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())'}))
6
dfichter

J'ai créé un panneau de complément que vous pouvez utiliser avec vos applications App Engine déployées. Il répertorie les types présents dans le magasin de données dans une liste déroulante et vous pouvez cliquer sur un bouton pour planifier des "tâches" qui suppriment toutes les entités d'un type spécifique ou simplement tout. Vous pouvez le télécharger ici:
http://code.google.com/p/jobfeed/wiki/Nuke

3
kostmo

La source

Je l'ai eu de http://code.google.com/appengine/articles/remote_api.html .

Créer la console interactive

Tout d’abord, vous devez définir une console d’application interactive. Donc, créez un fichier appelé appengine_console.py et entrez ceci:

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



Créer la classe de base du mappeur

Une fois que cela est en place, créez cette classe de mappeur. Je viens de créer un nouveau fichier appelé utils.py et j'ai lancé ceci:

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 est supposé être juste une classe abstraite qui vous permet d'itérer sur chaque entité d'un type donné, que ce soit pour extraire leurs données, ou pour les modifier et pour stocker les entités mises à jour dans le magasin de données.

Courez avec ça!

Maintenant, démarrez votre console interactive Appengine:

$python appengine_console.py <app_id_here>

Cela devrait démarrer la console interactive. Dans celui-ci créer une sous-classe de modèle:

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

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

Et enfin, lancez-le (depuis votre console interactive): mapper = MyModelDeleter () mapper.run ()

C'est ça!

3
Gezim

Ouvrez "Datastore Admin" pour votre application et activez Admin. Ensuite, toutes vos entités seront répertoriées avec des cases à cocher. Vous pouvez simplement sélectionner les entités indésirables et les supprimer.

3
Girish007

C'est ce que vous cherchez ...

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

L'exécution d'une requête portant uniquement sur des clés est beaucoup plus rapide qu'une extraction intégrale et votre quota aura un impact moins important, car les requêtes portant uniquement sur des clés sont considérées comme de petites opérations.

Voici un lien vers une réponse de Nick Johnson le décrivant plus en détail.

Vous trouverez ci-dessous une solution API de bout en bout REST) permettant de tronquer une table ...

J'ai configuré une REST pour gérer les transactions de base de données dans lesquelles les itinéraires sont directement mappés vers le modèle/l'action approprié. Cette opération peut être appelée en entrant l'URL correcte (example.com/inventory/truncate) et se connecter.

Voici l'itinéraire:

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

Voici le gestionnaire:

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

Il commence par charger le modèle de manière dynamique (par exemple, Inventory trouvé sous api.models), puis appelle la méthode appropriée (Inventory.truncate ()), comme indiqué dans le paramètre action.

@Basic_auth est un décorateur/wrapper qui fournit une authentification pour les opérations sensibles (par exemple, POST/DELETE). Il y a aussi un décorateur oAuth disponible si vous êtes préoccupé par la sécurité.

Enfin, l'action s'appelle:

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

Cela ressemble à de la magie mais en réalité c'est très simple. La meilleure partie est que delete () peut être réutilisé pour gérer la suppression d'un ou plusieurs résultats en ajoutant une autre action au modèle.

3
Evan Plaice

Pour Python, 1.3.8 inclut un administrateur expérimental intégré pour cela. Ils par exemple : "activent les éléments suivants dans votre fichier app.yaml:"

builtins:
- datastore_admin: on

"La suppression du magasin de données est actuellement disponible uniquement avec le moteur d'exécution Python. Les applications Java peuvent néanmoins tirer parti de cette fonctionnalité en créant une version d'application Python autre que celle par défaut qui permet à Datastore Admin de fonctionner. Le support natif de Java sera inclus dans une prochaine version. "

3
dfrankow

Vous pouvez supprimer tout le magasin de données en supprimant tous les types un par un. avec tableau de bord google appengine. S'il vous plaît suivez ces étapes.

  1. Connectez-vous à https://console.cloud.google.com/datastore/settings
  2. Cliquez sur Open Datastore Admin . (Activez-le s'il n'est pas activé.)
  3. Sélectionnez toutes les entités et appuyez sur la touche Suppr (cette étape exécute un travail de réduction de mappe pour supprimer tous les types sélectionnés).

pour plus d'informations, voir Cette image http://storage.googleapis.com/bnifsc/Screenshot%20from%202015-01-31%2023%3A58%3A41.png

3
vinay mavi

Vous pouvez le faire en utilisant l'interface Web. Connectez-vous à votre compte, naviguez avec des liens sur le côté gauche. Dans la gestion du magasin de données, vous avez des options pour modifier et supprimer des données. Utilisez les options respectives.

3
Priyank

Pour le serveur de développement, au lieu de l'exécuter via le programme de lancement du moteur d'applications Google, vous pouvez l'exécuter à partir du terminal, par exemple:

dev_appserver.py --port = [numéro de port] --clear_datastore = yes [nom de l'application]

ex: mon application "reader" fonctionne sur le port 15080. Après modification du code et redémarrage du serveur, je lance simplement "dev_appserver.py --port = 15080 --clear_datastore = yes reader".

C'est bon pour moi.

2
user1552891

Ajout de réponse sur les développements récents.

Google a récemment ajouté la fonctionnalité d'administration de magasin de données. Vous pouvez sauvegarder, supprimer ou copier vos entités dans une autre application à l'aide de cette console.

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

2
Vishwanath

Si vous avez beaucoup de données, l’utilisation de l’interface Web peut prendre beaucoup de temps. L'utilitaire App Engine Launcher vous permet de tout supprimer en une fois grâce à la case à cocher "Effacer le magasin de données au lancement". Cet utilitaire est maintenant disponible pour Windows et Mac (infrastructure Python).

2
lucrussell

Souvent, je ne veux pas supprimer tout le magasin de données, je tire donc une copie vierge de /war/WEB-INF/local_db.bin du contrôle de code source. C'est peut-être juste moi, mais il semble que même avec le mode Dev arrêté, je dois physiquement supprimer le fichier avant de le tirer. Ceci est sur Windows en utilisant le plugin Subversion pour Eclipse.

1
Dominic

J'étais tellement frustré par les solutions existantes pour la suppression de toutes les données du magasin de données dynamique que j'ai créé une petite application GAE capable de supprimer une assez grande quantité de données au sein de celui-ci. 30 secondes.

Comment installer etc: https://github.com/xamde/xydra

0
Dr. Max Völkel
  • en poursuivant l’idée de svpino, il est sage de réutiliser les enregistrements marqués comme supprimés. (son idée n'était pas de supprimer, mais de marquer comme "supprimé" les enregistrements inutilisés). un peu de cache/memcache pour gérer la copie de travail et écrire uniquement la différence d'états (avant et après la tâche souhaitée) dans le magasin de données le rendra meilleur. pour les grosses tâches, il est possible d'écrire des morceaux de différence immédiats dans le magasin de données afin d'éviter la perte de données si memcache disparaissait. pour éviter les pertes, il est possible de vérifier l’intégrité/l’existence des résultats memcached et de relancer la tâche (ou la partie requise) pour répéter les calculs manquants. lorsque la différence de données est écrite dans le magasin de données, les calculs requis sont ignorés dans la file d'attente.

  • une autre idée similaire à map réduit est de partager le type d’entité en plusieurs types d’entités, elle sera donc collectée et visible comme type d’entité unique pour l’utilisateur final. les entrées sont uniquement marquées comme "supprimées". lorsque le nombre d'entrées "supprimées" par fragment dépasse une certaine limite, les entrées "actives" sont réparties entre d'autres fragments, et ce fragment est définitivement fermé, puis supprimé manuellement de la console de développement (à moindre coût) upd: semble ne pas avoir de table de suppression sur la console, seulement supprimer enregistrement par enregistrement au prix habituel.

  • il est possible de supprimer par requête par morceaux un grand ensemble d'enregistrements sans échec de gae (au moins fonctionne localement) avec la possibilité de continuer à la prochaine tentative lorsque le temps est écoulé:


    qdelete.getFetchPlan().setFetchSize(100);

    while (true)
    {
        long result = qdelete.deletePersistentAll(candidates);
        LOG.log(Level.INFO, String.format("deleted: %d", result));
        if (result <= 0)
            break;
    }
  • il est également parfois utile de créer un champ supplémentaire dans la table primaire au lieu de placer les candidats (enregistrements associés) dans une table séparée. et oui, le champ peut être un tableau non indexé/sérialisé avec un faible coût de calcul.
0
Dmitry Bryliuk

Pour tout magasin de données utilisant le moteur d'applications plutôt que local, vous pouvez utiliser nouvelle API de magasin de données . Voici n guide pour commencer .

J'ai écrit un script qui supprime toutes les entités non intégrées. L'API change très rapidement, alors pour référence, je l'ai cloné au commit 990ab5c7f2063e8147bcc56ee222836fd3e6e15b

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 __== "__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
Yonatan Kogan

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

Fonctionne bien dans Development Server

0
Prakash Ayappan

Pour toutes les personnes ayant besoin d'une solution rapide pour le serveur de développement (au moment de la rédaction de cet article en février 2016):

  1. Arrêtez le serveur de dev.
  2. Supprimez le répertoire cible.
  3. Reconstruisez le projet.

Cela effacera toutes les données du magasin de données.

0
alexanderb14

Si vous utilisez ndb, la méthode qui a fonctionné pour moi pour effacer le magasin de données:

ndb.delete_multi(ndb.Query(default_options=ndb.QueryOptions(keys_only=True)))
0
Gilad Beeri
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
JQuery Guru

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

Oui, cela prendra du temps et 30 secondes. est une limite. Je pense mettre un exemple d'application ajax pour automatiser au-delà de 30 secondes.

0
MarkokraM