¿Cómo eliminar todo el almacén de datos en Google App Engine?

122

¿Alguien sabe cómo eliminar todo el almacén de datos en Google App Engine ?

Dan McGrath
fuente
2
db.delete (db.Query (keys_only = True)). Más detalles aquí stackoverflow.com/a/10856555/290340 .
Evan Plaice
44
Como lo señala @systempuntoout a continuación, GAE ahora tiene un administrador de almacén de datos que le permite eliminar entidades en masa sin ninguna codificación, entre otras cosas. Esa característica debe aparecer aquí en lugar de enterrarse en el tercer comentario.
ralfoide
El administrador del almacén de datos no funciona (la página carga un iframe a un host inexistente), por lo que aún tendríamos que usar el método db.delete.
Para eliminar todos los datos en el servidor de desarrollo, emita lo siguiente en cmd prompt: /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/ donde myappname es su directorio que contiene su archivo app.yaml para la aplicación ... necesita cd a esta ruta de directorio ... crédito: Steven Almeroth y Melllvar para la respuesta a continuación
gsinha

Respuestas:

69

Si está hablando del almacén de datos en vivo , abra el panel de su aplicación (inicie sesión en appengine), luego almacene el almacén de datos -> dataviewer, seleccione todas las filas de la tabla que desea eliminar y presione el botón Eliminar (deberá haz esto para todas tus mesas). Puede hacer lo mismo mediante programación a través de remote_api (pero nunca lo usé).

Si habla del almacén de datos de desarrollo , solo tendrá que eliminar el siguiente archivo: "./WEB-INF/appengine-generated/local_db.bin" . El archivo se generará nuevamente la próxima vez que ejecute el servidor de desarrollo y tendrá una base de datos clara.

Asegúrese de limpiar su proyecto después.

Esta es una de las pequeñas trampas que resultan útiles cuando comienzas a jugar con Google Application Engine. Te encontrarás persistiendo objetos en el almacén de datos y luego cambiando el modelo de objetos JDO para tus entidades persistentes que terminan con datos obsoletos que harán que tu aplicación se bloquee por todas partes.

JohnIdol
fuente
16
Hay un parámetro -c para dev_appserver.py para eliminar del almacén de datos de desarrollo.
svrist
1
@svrist Pero eso solo se aplica al motor de la aplicación Python. ¿Alguien sabe cómo un atajo para hacerlo en Java? (Mientras tanto, la sugerencia de JohnIdol funciona bien.)
mgiuca
2
Gracias @ John: ¿Dónde está la ruta exacta en MAC OSX?
George Nguyen
3
¿Dónde está el camino en Windows?
Shane Best
2
@ShaneBest el camino en windows es algo así como ./target/yourappid-1.0-SNAPSHOT/WEB-INF/appengine-generated/local_db.bin
morpheus
58

El mejor enfoque es el método de API remota como lo sugiere Nick, es un ingeniero de App Engine de Google , así que confía en él.

No es tan difícil de hacer, y el último 1.2.5 SDK proporciona el remote_shell_api.py fuera de la plataforma. Así que vaya a descargar el nuevo SDK. Luego sigue los pasos:

  • conecte el servidor remoto en su línea de comandos: remote_shell_api.py yourapp /remote_api el shell le pedirá su información de inicio de sesión y, si está autorizado, creará un shell Python para usted. Necesita configurar el controlador de URL para / remote_api en su aplicación.

  • busque las entidades que desea eliminar, el código se ve así:

    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

Actualización 2013-10-28 :

  • remote_shell_api.pyha sido reemplazado por remote_api_shell.py, y debe conectarse con remote_api_shell.py -s your_app_id.appspot.com, de acuerdo con la documentación .

  • Hay una nueva función experimental de administrador de almacén de datos, después de habilitarla en la configuración de la aplicación, puede eliminar en masa y hacer una copia de seguridad de su almacén de datos a través de la interfaz de usuario web.

Juvenn Woo
fuente
17
En realidad, no necesitas la búsqueda. Solo db.delete (Entry.all ()) lo hará.
descargar
44
Debe hacer esto en 500 conjuntos de entidades o de lo contrario obtendrá: BadRequestError: no puede eliminar más de 500 entidades en una sola llamada
marcc
1
Solo para su información, para que pueda usar la API remota, primero debe habilitarla en su aplicación usando builtins: - remote_api: en su archivo YAML. más información está en developers.google.com/appengine/articles/remote_api
Zaffiro
2
Al menos agregue 'keys_only = True' cuando llame a Entry.all (). No es necesario recuperar toda la entrada si no necesita verificar los datos. De lo contrario, solo estás desperdiciando ciclos informáticos.
Evan Plaice
1
+1 ... pero: a partir de 2013, remote_shell_api.py no existe. El nombre del script actual es remote_api_shell.py. Además, si usa ndb (que es lo que hace la mayoría de la gente en estos días), forma recomendada de usar ndb.delete_multi (model.Entry.query (). Fetch (keys_only = True))
Uri
27

La forma más rápida y eficiente de manejar la eliminación masiva en Datastore es mediante el uso de la nueva API de mapeador anunciada en la última E / S de Google .

Si su idioma de elección es Python , solo tiene que registrar su mapeador en un archivo mapreduce.yaml y definir una función como esta:

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

En Java , debería echar un vistazo a este artículo que sugiere una función 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());
}

EDITAR:
desde SDK 1.3.8, hay una función de administración del almacén de datos para este propósito

systemmpuntoout
fuente
27

Puede borrar el almacén de datos del servidor de desarrollo cuando ejecuta el servidor:

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

También puedes abreviar --clear_datastorecon -c.

Steven Almeroth
fuente
55
No estoy seguro si es algo reciente, pero la sintaxis real es ahora /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/(tenga en cuenta el 'sí')
Melllvar
Es la forma más útil de eliminar repetidamente el almacén de datos durante el desarrollo. Con las opciones obsoletas rápidamente, vale la pena resaltar que esta bandera todavía está en su lugar en julio de 2018, y funciona para dev_appserver instalado a través de CLI de gcloud
Michael
En la versión 270.0.0 del SDK de Google Cloud "--clear_datastore = yes" todavía funciona con el signo igual
franksands
15

Si tiene una cantidad significativa de datos, debe usar un script para eliminarlos. Sin embargo, puede usar remote_api para borrar el almacén de datos del lado del cliente de una manera directa.

Nick Johnson
fuente
11

Aquí tiene: vaya al administrador del almacén de datos y luego seleccione el tipo de entidad que desea eliminar y haga clic en Eliminar. ¡Mapreduce se encargará de eliminar!

David
fuente
9

Existen varias formas de eliminar entradas del almacén de datos de App Engine:

ingrese la descripción de la imagen aquí

  1. Primero, piense si realmente necesita eliminar entradas. Esto es costoso y puede ser más barato no eliminarlos.

  2. Puede eliminar todas las entradas a mano con el administrador del almacén de datos.

  3. Puede usar la API remota y eliminar entradas de forma interactiva.

  4. Puede eliminar las entradas mediante programación mediante un par de líneas de código.

  5. Puede eliminarlos de forma masiva utilizando las Colas de tareas y los cursores.

  6. O puede usar Mapreduce para obtener algo más robusto y elegante.

Cada uno de estos métodos se explica en la siguiente publicación de blog: http://www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore

¡Espero eso ayude!

svpino
fuente
6

La forma de configuración cero para hacer esto es enviar una solicitud HTTP de código arbitrario de ejecución al servicio de administración que su aplicación en ejecución ya tiene, de forma automática:

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
fuente
Esto solo funciona para el servidor de desarrollo. ¿Hay un equivalente de producción?
Gady
3

Fuente

Obtuve esto de http://code.google.com/appengine/articles/remote_api.html .

Crear la consola interactiva

Primero, debe definir una consola de anexos interactiva. Entonces, cree un archivo llamado appengine_console.py e ingrese esto:

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



Crear la clase base de Mapper

Una vez que esté en su lugar, cree esta clase Mapper. Acabo de crear un nuevo archivo llamado utils.py y lancé esto:

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)

Se supone que Mapper es solo una clase abstracta que le permite iterar sobre cada entidad de un tipo dado, ya sea para extraer sus datos o para modificarlos y almacenar las entidades actualizadas nuevamente en el almacén de datos.

¡Corre con eso!

Ahora, inicie su consola interactiva appengine:

$python appengine_console.py <app_id_here>

Eso debería iniciar la consola interactiva. En él crea una subclase de Modelo:

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

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

Y, finalmente, ejecútelo (desde su consola interactiva): mapper = MyModelDeleter () mapper.run ()

¡Eso es!

Gezim
fuente
3

Puedes hacerlo usando la interfaz web. Inicie sesión en su cuenta, navegue con enlaces en el lado izquierdo. En la gestión del Almacén de datos, tiene opciones para modificar y eliminar datos. Use las opciones respectivas.

Priyank
fuente
3

Creé un panel de complementos que se puede usar con sus aplicaciones de App Engine implementadas. Enumera los tipos que están presentes en el almacén de datos en un menú desplegable, y puede hacer clic en un botón para programar "tareas" que eliminen todas las entidades de un tipo específico o simplemente todo. Puede descargarlo aquí:
http://code.google.com/p/jobfeed/wiki/Nuke

kostmo
fuente
3

Para Python, 1.3.8 incluye un administrador experimental incorporado para esto. Ellos dicen : "habilitar las siguientes incorporado en su archivo app.yaml:"

builtins:
- datastore_admin: on

"La eliminación del almacén de datos actualmente está disponible solo con el tiempo de ejecución de Python. Sin embargo, las aplicaciones Java aún pueden aprovechar esta característica al crear una versión de la aplicación Python no predeterminada que habilita Datastore Admin en app.yaml. Se incluirá soporte nativo para Java en un próximo lanzamiento ".

dfrankow
fuente
Agregar la configuración en app.yaml arrojó un error. En cambio, podemos habilitarlo desde la página 'Configuración de aplicaciones' en la sección 'Administración'. Hay un botón para habilitarlo
Sundeep
3

Abra "Datastore Admin" para su aplicación y habilite Admin. Luego, todas sus entidades se enumerarán con casillas de verificación. Simplemente puede seleccionar las entidades no deseadas y eliminarlas.

Girish007
fuente
3

Esto es lo que estás buscando ...

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

Ejecutar una consulta de solo claves es mucho más rápido que una búsqueda completa, y su cuota tendrá un impacto menor porque las consultas de solo claves se consideran operaciones pequeñas.

Aquí hay un enlace a una respuesta de Nick Johnson que lo describe más a fondo.

A continuación se muestra una solución API REST de extremo a extremo para truncar una tabla ...

Configuré una API REST para manejar transacciones de bases de datos donde las rutas se asignan directamente al modelo / acción adecuado. Se puede llamar ingresando la URL correcta (example.com/inventory/truncate) e iniciando sesión.

Aquí está la ruta:

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

Aquí está el controlador:

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

Comienza cargando el modelo dinámicamente (es decir, Inventario encontrado en api.models), luego llama al método correcto (Inventory.truncate ()) como se especifica en el parámetro de acción.

@Basic_auth es un decorador / contenedor que proporciona autenticación para operaciones confidenciales (es decir, POST / DELETE). También hay un decorador oAuth disponible si le preocupa la seguridad.

Finalmente, la acción se llama:

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

Parece magia, pero en realidad es muy sencillo. La mejor parte es que delete () se puede reutilizar para manejar la eliminación de uno o muchos resultados agregando otra acción al modelo.

Evan Plaice
fuente
3

Puede eliminar todo el almacén de datos eliminando todos los tipos uno por uno. con el tablero de instrumentos google appengine. Por favor, siga estos pasos.

  1. Inicie sesión en https://console.cloud.google.com/datastore/settings
  2. Haga clic en Abrir administrador de almacén de datos . (Habilítelo si no está habilitado).
  3. Seleccione todas las entidades y presione eliminar. (Este paso ejecuta un mapa para reducir el trabajo para eliminar todos los tipos seleccionados).

Para obtener más información, consulte esta imagen http://storage.googleapis.com/bnifsc/Screenshot%20from%202015-01-31%2023%3A58%3A41.png

vinay mavi
fuente
2

Si tiene muchos datos, el uso de la interfaz web puede llevar mucho tiempo. La utilidad App Engine Launcher le permite eliminar todo de una vez con la casilla de verificación 'Borrar almacén de datos al iniciar'. Esta utilidad ahora está disponible para Windows y Mac (marco de Python).

lucrussell
fuente
2

Para el servidor de desarrollo, en lugar de ejecutar el servidor a través del iniciador del motor de aplicaciones de Google, puede ejecutarlo desde la terminal como:

dev_appserver.py --port = [número de puerto] --clear_datastore = yes [nameofapplication]

Ej: mi aplicación "reader" se ejecuta en el puerto 15080. Después de modificar el código y reiniciar el servidor, simplemente ejecuto "dev_appserver.py --port = 15080 --clear_datastore = yes reader".

Es bueno para mí.

usuario1552891
fuente
1

A menudo no quiero eliminar todo el almacén de datos, así que saco una copia limpia de /war/WEB-INF/local_db.bin fuera del control de código fuente. Puede que solo sea yo, pero parece que incluso con el modo Dev detenido tengo que eliminar físicamente el archivo antes de extraerlo. Esto está en Windows usando el complemento de subversión para Eclipse.

Dominic
fuente
0

Variación de 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í, llevará tiempo y 30 segundos. Es un límite. Estoy pensando en poner una muestra de la aplicación ajax para automatizar más allá de 30 segundos.

MarkokraM
fuente
Esto ni siquiera es válido php. import? ¿Definir una constante como una instancia de objeto?
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
fuente
0

Si está utilizando ndb, el método que funcionó para mí para borrar el almacén de datos:

ndb.delete_multi(ndb.Query(default_options=ndb.QueryOptions(keys_only=True)))
Gilad Beeri
fuente
1
No creo que esto funcione. Appengine se queja acerca de Sorry, unexpected error: The kind "__Stat_Kind__" is reserved.Esto parece que appengine tiene alguna entidad de estadística interna que puede ser expuesta por este método (¿posible error de su parte?)
desapareció el
0

Para cualquier almacén de datos que esté en el motor de la aplicación, en lugar de local, puede usar la nueva API del almacén de datos . Aquí hay una introducción a cómo comenzar .

Escribí un script que elimina todas las entidades no integradas. La API está cambiando bastante rápido, así que para referencia, la cloné en 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
fuente
0
  • Continuando con la idea de svpino, es aconsejable reutilizar los registros marcados como eliminar. (su idea no era eliminar, sino marcar como registros "eliminados" no utilizados). un poco de caché / memoria caché para manejar la copia de trabajo y escribir solo la diferencia de estados (antes y después de la tarea deseada) en el almacén de datos lo mejorará. Para tareas grandes es posible escribir fragmentos de diferencia inmediata en el almacén de datos para evitar la pérdida de datos si Memcache desapareció. Para que sea a prueba de pérdidas, es posible verificar la integridad / existencia de los resultados de Memcached y reiniciar la tarea (o parte requerida) para repetir los cálculos faltantes. cuando la diferencia de datos se escribe en el almacén de datos, los cálculos necesarios se descartan en la cola.

  • Otra idea similar al mapa reducido es dividir el tipo de entidad en varios tipos de entidad diferentes, por lo que se recopilará y será visible como un tipo de entidad única para el usuario final. las entradas solo se marcan como "eliminadas". cuando la cantidad de entradas "eliminadas" por fragmento supera algún límite, las entradas "vivas" se distribuyen entre otros fragmentos, y este fragmento se cierra para siempre y luego se elimina manualmente de la consola de desarrollo (supongo que a menor costo) upd: parece que no hay una tabla desplegable en la consola, solo elimine registro por registro a precio regular.

  • es posible eliminar por consulta un gran conjunto de registros sin que gae falle (al menos funciona localmente) con la posibilidad de continuar en el próximo intento cuando se acabe el tiempo:


    qdelete.getFetchPlan().setFetchSize(100);

    while (true)
    {
        long result = qdelete.deletePersistentAll(candidates);
        LOG.log(Level.INFO, String.format("deleted: %d", result));
        if (result <= 0)
            break;
    }
  • También a veces es útil hacer un campo adicional en la tabla primaria en lugar de poner candidatos (registros relacionados) en una tabla separada. y sí, el campo puede ser una matriz no indexada / serializada con un bajo costo de cálculo.
Dmitry Bryliuk
fuente
0

Para todas las personas que necesitan una solución rápida para el servidor de desarrollo (al momento de escribir en febrero de 2016):

  1. Detenga el servidor de desarrollo.
  2. Eliminar el directorio de destino .
  3. Reconstruir el proyecto.

Esto borrará todos los datos del almacén de datos.

alexanderb14
fuente
0

Estaba muy frustrado por las soluciones existentes para eliminar todos los datos en el almacén de datos en vivo que creé una pequeña aplicación GAE que puede eliminar una gran cantidad de datos en sus 30 segundos.

Cómo instalar, etc.: https://github.com/xamde/xydra

Dr. Max Völkel
fuente
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 bien en el servidor de desarrollo

Prakash Ayappan
fuente
0

Tienes 2 formas simples,

# 1: para ahorrar costos, elimine todo el proyecto

# 2: usando ts-datastore-orm:

https://www.npmjs.com/package/ts-datastore-orm await Entity.truncate (); El truncado puede eliminar alrededor de 1K filas por segundo

Tsang Kin Ho
fuente