Pregunta sobre google-app-engine, google-cloud-datastore – ¿Cómo eliminar todos los almacenes de datos en Google App Engine?

122

¿Alguien sabe cómo eliminar todos los almacenes de datos enMotor de aplicaciones de Google?

Como se señala a continuación por @systempuntoout, GAE ahora tiene unAdministrador del almacén de datos que le permite eliminar entidades de forma masiva sin ningún tipo de codificación, entre otras cosas. Esa característica debe aparecer aquí en lugar de ser enterrada en el tercer comentario. ralfoide
db.delete (db.Query (keys_only = True)). Más detalles aquístackoverflow.com/a/10856555/290340. Evan Plaice
Para eliminar todos los datos en el servidor de desarrollo, emita lo siguiente en el indicador de cmd:/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 ingresar a esta ruta del directorio ... Crédito: Steven Almeroth y Melllvar para la respuesta a continuación. gsinha
El Administrador del almacén de datos no funciona (la página carga un iframe a un host inexistente), por lo que todavía necesitamos usar el método db.delete. user153275
db.delete(db.Query()) Andrey Gubarev

Tu respuesta

27   la respuesta
2

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

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

ej: mi aplicación "lector" 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í.

11

Aquí tiene: Vaya a Admin del almacén de datos, seleccione el tipo de entidad que desea eliminar y haga clic en Eliminar. Mapreduce se encargará de eliminar!

3

He creado un panel de complementos que se puede usar con las 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 eliminan todas las entidades de un tipo específico o simplemente todo. Puedes descargarlo aquí:
http://code.google.com/p/jobfeed/wiki/Nuke

15

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

26

Usted puedeborrar 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_datastore con-c.

Doble bono por menos pulsaciones de teclas! nate_weldon
También puede abreviar "--clear_datastore" con "-c". Steven Almeroth
No estoy seguro de si es algo reciente, pero la sintaxis actual es ahora/path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/ (note el 'si') Melllvar
Gracias @Melllvar, respuesta actualizada. Steven Almeroth
Es la forma más útil de eliminar repetidamente el almacén de datos durante el desarrollo. Con las opciones que se están quedando obsoletas rápidamente, vale la pena resaltar que esta bandera aún está vigente en julio de 2018 y funciona para dev_appserver instalado a través de la CLI de gcloud Michael
1

A menudo no quiero eliminar todo el almacén de datos, así que extraigo una copia limpia de /war/WEB-INF/local_db.bin del control de origen. 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.

3
Fuente

Tengo esto dehttp://code.google.com/appengine/articles/remote_api.html.

Crear la consola interactiva

Primero, necesitas definir una consola de aplicaciones 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 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 el asignador es solo una clase abstracta que le permite iterar sobre cada entidad de un tipo dado, ya sea para extraer sus datos, o modificarlos y almacenar las entidades actualizadas en el almacén de datos.

Corre con ello!

Ahora, inicia tu 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útalo (desde tu consola interactiva): mapper = MyModelDeleter () mapper.run ()

¡Eso es!

0

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

Detener el servidor dev.Eliminar elobjetivo directorio.Reconstruir el proyecto.

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

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
3

Puedes hacerlo utilizando la interfaz web. Inicie sesión en su cuenta, navegue con los enlaces en el lado izquierdo. En la gestión de Data Store tienes opciones para modificar y eliminar datos. Usa las respectivas opciones.

2

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

0

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)))
No creo que esto funcione. Appengine se queja deSorry, unexpected error: The kind "__Stat_Kind__" is reserved. Esto parece que Appengine tiene alguna entidad estadística interna que puede ser expuesta por este método (¿posible error en su final?) disappearedng
3

Esto es lo que estás buscando ...

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

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

Aquí está unenlace a una respuesta de Nick Johnson describiéndolo más a fondo.

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

Configuré una API REST para manejar transacciones de base de datos donde las rutas se asignan directamente al modelo / acción adecuado. Esto 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.

El @basic_auth es un decorador / envoltorio que proporciona autenticación para operaciones sensibles (es decir, POST / DELETE). También hay unoAuth decorator 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 eliminar uno o varios resultados agregando otra acción al modelo.

69

Si estás hablando de laalmacén de datos en vivo, abra el panel de control de su aplicación (inicie sesión en appengine), luego almacén de datos -> dataviewer, seleccione todas las filas de la tabla que desea eliminar y presione el botón de eliminar (tendrá que hacer esto para todas sus tablas). Puedes hacer lo mismo programáticamente a través de remote_api (pero nunca lo usé).

Si estás hablando de ladesarrollo de datos, solo tendrás que borrar 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úrate de limpiar tu proyecto después.

Este es uno de los pequeños errores que son útiles cuando empiezas a jugar con Google Application Engine. Encontrará objetos persistentes en el almacén de datos y luego cambiará el modelo de objetos JDO para sus entidades persistentes y obtendrá datos obsoletos que harán que su aplicación se bloquee por todas partes.

@ShaneBest la ruta en Windows es algo así como ./target/yourappid-1.0-SNAPSHOT/WEB-INF/appengine-generated/local_db.bin morpheus
Gracias @John: ¿Dónde está la ruta exacta en MAC OSX? George Nguyen
Hay un parámetro -c en dev_appserver.py para eliminar del almacén de datos de desarrollo. svrist
Me refiero al almacén de datos en el servidor de Google Appengine manman
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:

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())'}))
Esto solo funciona para el servidor de desarrollo. ¿Hay un equivalente de producción? Gady
Brillante, exactamente lo que necesitaba en mi caso. Mason
3

Datastore Admin" para su aplicación y habilite Admin. Entonces todas sus entidades serán listadas con casillas de verificación. Simplemente puede seleccionar los entites no deseados y eliminarlos.

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

3

Puede eliminar todos los almacenes de datos eliminando todos los tipos uno por uno. con el tablero de instrumentos de Google Appengine. Por favor siga estos pasos.

Iniciar sesión enhttps://console.cloud.google.com/datastore/settingsHacer clicAbra el administrador del almacén de datos. (Habilitarlo si no está habilitado).Seleccione todas las entidades y presione eliminar. (Este paso ejecuta un trabajo de reducción de mapa para eliminar todos los tipos seleccionados).

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

58

El mejor enfoque es el método de API remota sugerido por Nick, él es unMotor de aplicaciones ingeniero deGoogle, 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 ve a descargar el nuevo SDK. Luego sigue los pasos:

conecte el servidor remoto en su linea de comando:remote_shell_api.py yourapp /remote_api El shell solicitará su información de inicio de sesión y, si está autorizado, creará un shell de Python para usted. Necesita configurar el controlador de URL para / remote_api en su app.yaml

Busca las entidades que te gustaría eliminar, el código se ve algo así como:

    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.py ha sido reemplazado porremote_api_shell.py, y debes conectarte conremote_api_shell.py -s your_app_id.appspot.com, de acuerdo ala documentación.

Hay una nueva característica experimental.Administrador del almacén de datosDespués de habilitarla en la configuración de la aplicación, puede eliminar de forma masiva y hacer una copia de seguridad del almacén de datos a través de la interfaz de usuario web.

Gracias Evan, he añadidokeys_only=True como sugeriste. Juvenn Woo
Solo un FYI, para que uses el api remoto, primero debes habilitarlo en tu aplicación utilizando los elementos integrados: - remote_api: en tu archivo YAML. más información está endevelopers.google.com/appengine/articles/remote_api Zaffiro
@Uri Echa un vistazo a laremote_api_shell.py que provienen del SDK, podría ser una buena demostración de cómo debe comunicarse su script con el almacén de datos remoto. Lo siento por la respuesta tardía, y no he jugado con appengine mucho recientemente. Juvenn Woo
En realidad, no necesitas la búsqueda. Solo db.delete (Entry.all ()) lo hará. download
3

Para Python, 1.3.8 incluye un administrador experimental incorporado para esto. Ellosdecir: "habilita el siguiente contenido incorporado en tu 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 función mediante la creación de una versión de la aplicación Python no predeterminada que permite la administración del almacén de datos en app.yaml. Se incluirá soporte nativo para Java en un próximo lanzamiento ".

esa es la solución más fácil actualmente para eliminar en masa una entidad específica systempuntoout
Agregando la configuración en app.yaml lanzó un error. En su lugar, podemos habilitarlo desde la página 'Configuración de aplicaciones' en la sección 'Administración'. Hay un botón para habilitarlo. Sundeep
27

almacén de datos es utilizando el nuevoAPI de mapeador anunciado en la últimaGoogle I / O.

Si su idioma de elección esPitón, solo tienes que registrar tu mapeador en unmapreduce.yaml archiva y define una función como esta:

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

EnJava deberías echar un vistazo aEste artículo Eso 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 el SDK 1.3.8, hay unFunción de administrador del almacén de datos para este propósito

Realmente impresionante. Gracias. Guido
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í tomará tiempo y 30 seg. es un limite Estoy pensando en poner una muestra de la aplicación ajax para automatizar más de 30 segundos.

Esto ni siquiera es válido php.import? ¿Definiendo una constante como una instancia de objeto? Josh J
WTF? Nada de eso es necesario. Evan Plaice
9

Hay varias formas que puede usar para eliminar entradas del almacén de datos de App Engine:

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

Puede eliminar todas las entradas a mano utilizando el Administrador del almacén de datos.

Puede utilizar la API remota y eliminar entradas de forma interactiva.

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

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

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 del blog:http://www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore

¡Espero eso ayude!

0

borrando todos los datos en el almacén de datos en vivo que creé una pequeña aplicación GAE que puede eliminar una cantidad considerable de datos en sus 30 segundos.

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

2

Google ha agregado recientemente la función de administración de datos. Puede hacer una copia de seguridad, eliminar o copiar sus entidades a otra aplicación usando esta consola.

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

0

Para cualquier almacén de datos que esté en el motor de la aplicación, en lugar de local, puede usar elnueva API de almacén de datos. Aquí estáuna cartilla de cómo empezar.

Escribí un script que borra todas las entidades no integradas. La API está cambiando bastante rápido, así que para referencia, la cloné en la confirmación990ab5c7f2063e8147bcc56ee222836fd3d6e15b

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

Continuando con la idea de svpino, es prudente reutilizar los registros marcados como eliminados. (Su idea no era eliminar, sino marcar como "no eliminado" los registros no utilizados). Un poco de caché / memcache para manejar la copia y escritura en funcionamiento, y la diferencia de estados (antes y después de la tarea deseada) en el almacén de datos lo hará mejor. para grandes tareas es posible escribir itermediate diferencia fragmentos en el almacén de datos para evitar la pérdida de datos si desaparece memcache. para hacerlo a prueba de pérdidas, es posible verificar la integridad / existencia de los resultados de memcached y reiniciar la tarea (o la 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 a la del mapa reducido es dividir el tipo de entidad en varios tipos de entidad diferentes, por lo que se recopilará y será visible como tipo de entidad única para el usuario final. las entradas solo están marcadas como "eliminadas". cuando la cantidad de entradas "eliminadas" por fragmento supera algún límite, las entradas "activas" se distribuyen entre otros fragmentos, y este fragmento se cierra para siempre y luego se elimina manualmente desde la consola dev (supongo que a menor costo) upd: parece que no hay una tabla desplegable en la consola, solo borra registro por registro a precio regular.

es posible eliminar por consulta mediante un gran conjunto de registros sin errores gae (al menos funciona localmente) con 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;
    }
a veces también es útil hacer un campo adicional en la tabla principal en lugar de colocar candidatos (registros relacionados) en una tabla separada. y sí, el campo puede ser una matriz no indexada / serializada con poco costo de cómputo.

Preguntas relacionadas