standard google features engine change app google-app-engine google-cloud-datastore

google-app-engine - features - google app engine flex vs standard



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

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


Fuente

Obtuve esto de .

Crear la consola interactiva

Primero, necesita definir una consola de appenginge interactiva. Por lo tanto, 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, crea esta clase de 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 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 comenzar 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!


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


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



Aquí tienes: ve al administrador de Datastore, y luego selecciona el tipo de entidad que deseas eliminar y haz clic en Eliminar. ¡Mapreduce se encargará de eliminar!


Creé un panel de complementos que se puede usar con las aplicaciones implementadas de App Engine. 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


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

  • conecte el servidor remoto en su línea de comando: 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 de Python para usted. Necesitas configurar el controlador de URL para / remote_api en tu 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 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 característica experimental Administrador de Datastore , después de habilitarlo en la configuración de la aplicación, puede eliminar en bloque y hacer una copia de seguridad de su almacén de datos a través de la interfaz de usuario web.


Estaba tan frustrado con 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 bastante cantidad de datos en 30 segundos.

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


Existen varias formas de eliminar entradas del Datastore de App Engine:

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

  2. Puede eliminar todas las entradas a mano usando el Administrador de Datastore.

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

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

  5. Puede eliminarlos a granel utilizando Task Queues and Cursors.

  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!


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

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


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 correlación anunciada en el último Google I / O.

Si su idioma de elección es Python , solo tiene que registrar su mapper 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ías 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 administrador de Datastore para este propósito


Para Python, 1.3.8 incluye un administrador experimental incorporado para esto. say : "habilite el siguiente comando integrado en su archivo app.yaml:"

builtins: - datastore_admin: on

"Datastore delete actualmente solo está disponible 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 aplicación Python no predeterminada que habilita Datastore Admin en la aplicación.yaml. Se incluirá soporte nativo para Java. en un próximo lanzamiento ".


Para cualquier almacén de datos que esté en el motor de la aplicación, en lugar de local, puede usar la nueva API de Datastore . Aquí hay un manual para comenzar .

Escribí un script que elimina todas las entidades no incorporadas. La API está cambiando bastante rápido, así que como referencia, la 990ab5c7f2063e8147bcc56ee222836fd3d6e15b 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()


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 = [portnumber] --clear_datastore = yes [nameofapplication]

por ejemplo: 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í.


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


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

  1. Detener el servidor de desarrollo.
  2. Eliminar el directorio de destino .
  3. Reconstruye el proyecto.

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



Puede eliminar todo el almacén de datos borrando todos los tipos uno a uno. con google appengine tablero de instrumentos. Por favor sigue estos pasos.

  1. Inicie sesión en https://console.cloud.google.com/datastore/settings
  2. Haga clic en Abrir administrador de Datastore . (Habilítelo si no está habilitado)
  3. Seleccione todas las entidades y presione eliminar. (Este paso ejecutar un mapa reduce trabajo para eliminar todas las clases seleccionadas.)

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


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


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

Si está hablando del almacén de datos de desarrollo , simplemente tendrá que eliminar el siguiente archivo: "./WEB-INF/appengine-generated/local_db.bin" . El archivo se generará para usted nuevamente la próxima vez que ejecute el servidor de desarrollo y tendrá un db claro.

Asegúrese de limpiar su proyecto después.

Este es uno de los pequeños inconvenientes que son útiles cuando comienzas a jugar con Google Application Engine. Encontrarás objetos persistentes en el almacén de datos y luego cambiarás el modelo de objetos JDO para tus entidades persistentes terminando con datos obsoletos que harán que tu aplicación falle por doquier.


Si está usando 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)))


Si tiene muchos datos, usar la interfaz web podría llevar mucho tiempo. La utilidad App Engine Launcher te 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 para Windows y Mac (framework de Python).


Si tiene una gran cantidad de datos, debe usar un script para eliminarlo. Sin embargo, puedes usar remote_api para limpiar el almacén de datos del lado del cliente.


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 seg. es un limite Estoy pensando en poner una muestra de la aplicación ajax para automatizar más allá de 30 segundos.


Esto es lo que estás buscando ...

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

Ejecutar una consulta de solo teclas 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 continuación se muestra una solución de API REST de extremo a extremo para truncar una tabla ...

Configuré una API REST para manejar las transacciones de la base de datos donde las rutas se asignan directamente al modelo / acción adecuado. Esto se puede invocar 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 confidenciales (es decir, POST / DELETE). También hay un decorador de OAuth disponible si le preocupa la seguridad.

Finalmente, la acción se llama:

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

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


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


  • Continuando con la idea de svpino, es prudente reutilizar los registros marcados como eliminar. (su idea no era eliminar, sino marcar como registros "no utilizados"). Un poco de caché / memcache 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 diferencias inmediatas en el almacén de datos para evitar la pérdida de datos si desaparecía Memcache. para que sea 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 requeridos se descartan en la cola.

  • Otra idea similar al mapa reducido es el tipo de entidad de fragmento de varios tipos de entidades diferentes, por lo que se recopilarán juntos y se mostrarán como entidad única para el usuario final. las entradas solo se marcan como "eliminadas". cuando las entradas "eliminadas" ascienden 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 borra manualmente de la consola de desarrollo (adivinar a menor costo) upd: parece que no hay tabla desplegable en la consola solo elimine registro por registro a precio regular.

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

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 colocar candidatos (registros relacionados) en una tabla separada. y sí, el campo puede ser array no indexado / serializado con un pequeño costo de cálculo.