Як видалити всі сховища даних у Google App Engine?


122

Хтось знає, як видалити всі сховища даних у Google App Engine ?


2
db.delete (db.Query (keys_only = True)). Більш детальна інформація тут stackoverflow.com/a/10856555/290340 .
Еван Плейс

4
Як вказує @systempuntoout нижче, GAE тепер має адміністратор Datastore, який дозволяє, крім іншого, видаляти об'єкти масово, без будь-якого кодування. Цю особливість потрібно тут з'явити, а не поховати в 3-му коментарі.
ralfoide

Адміністратор Datastore не працює (сторінка завантажує кадр iframe на неіснуючий хост), тому нам все одно потрібно використовувати метод db.delete.

Щоб видалити всі дані на сервері розробки, /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/ надрукуйте наступне в підказці cmd: де myappname - ваш каталог, що містить ваш файл app.yaml для програми .. вам потрібно перейти на цей шлях до каталогу. Кредит: Стівен Алмерот та Мелллвар для відповіді нижче
gsinha

Відповіді:


69

Якщо ви говорите про прямий сховище даних , відкрийте панель інструментів для свого додатка (вхід на додаток), а потім сховище даних -> переглядач даних, виберіть усі рядки таблиці, яку потрібно видалити, і натисніть кнопку видалення (вам доведеться зробіть це для всіх своїх таблиць). Ви можете зробити те саме програмно через remote_api (але я його ніколи не використовував).

Якщо ви говорите про сховище даних про розробку , вам просто доведеться видалити такий файл: "./WEB-INF/appengine-generated/local_db.bin" . Цей файл буде генерований для вас знову під час запуску сервера розробки, і у вас буде чіткий db.

Переконайтесь, що після цього почистіть проект.

Це один із маленьких прихильників, які стануть у нагоді, коли ви починаєте грати з Google Application Engine. Ви виявите, що в сховищі даних зберігаються об'єкти, а потім зміните об'єктну модель JDO для своїх стійких організацій, що закінчується застарілими даними, які змусять ваш додаток повсюдно зазнавати аварії.


16
Для dev_appserver.py є параметр -c, який потрібно видалити з магазину даних розробки.
церіст

1
@svrist Але це стосується лише двигуна додатків Python. Хтось знає, як це ярлик для цього на Java? (Тим часом, пропозиція JohnIdol працює добре.)
mgiuca

2
Дякую @John: Де точний шлях у MAC OSX?
Джордж Нгуен

3
Де шлях у Windows?
Шейн Кращий

2
@ShaneBest шлях у вікнах що - щось на зразок ./target/yourappid-1.0-SNAPSHOT/WEB-INF/appengine-generated/local_db.bin
Дзига

58

Найкращий підхід - це віддалений метод API, як запропонував Нік, він інженер App Engine від Google , тому довіряйте йому.

Це не так складно зробити, і останній 1.2.5 SDK забезпечує віддалений_шал_апі.py з полиці. Тож перейдіть до завантаження нового SDK. Потім виконайте кроки:

  • підключіть віддалений сервер у вашому командному рядку: remote_shell_api.py yourapp /remote_api оболонка запитає вашу інформацію про вхід, і якщо вона буде авторизована, зробить оболонку Python для вас. Вам потрібен обробник URL-адреси налаштування для / remote_api у вашому app.yaml

  • виберіть об'єкти, які ви хочете видалити, код виглядає приблизно так:

    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

Оновлення 2013-10-28 :

  • remote_shell_api.pyбуло замінено remote_api_shell.py, і вам слід з'єднатися з цим remote_api_shell.py -s your_app_id.appspot.com, згідно з документацією .

  • Існує нова експериментальна функція Datastore Admin , після ввімкнення її в налаштуваннях додатків ви можете масово видаляти, а також створювати резервну копію ваших сховищ даних через веб-інтерфейс.


17
Насправді ви не потребуєте цього. Просто db.delete (Entry.all ()) зробить це.
завантажити

4
Вам потрібно зробити це в 500 наборах об'єктів, інакше ви отримаєте: BadRequestError: не можна видалити більше 500 об'єктів за один виклик
marcc

1
Просто FYI, щоб використовувати віддалений api, потрібно ввімкнути його у вашій програмі спочатку за допомогою вбудованих файлів: - remote_api: у вашому файлі YAML. докладнішу інформацію можна знайти на developers.google.com/appengine/articles/remote_api
Zaffiro

2
Принаймні додайте "keys_only = True", коли ви телефонуєте Entry.all (). Немає необхідності отримувати весь запис, якщо вам не потрібно перевіряти дані. Ще ви просто витрачаєте обчислювальні цикли.
Еван Плейс

1
+1 ... але: Станом на 2013 рік, remote_shell_api.py не існує. Поточне ім'я сценарію - remote_api_shell.py. Крім того, якщо ви використовуєте ndb (саме це робить більшість людей в ці дні), рекомендований спосіб використання ndb.delete_multi (model.Entry.query (). Fetch (keys_only = True))
Uri

27

Найшвидший та найефективніший спосіб обробляти масове видалення в Datastore - це використання нового API-картографа, оголошеного в останньому вході / виводу Google .

Якщо обраною вами мовою є Python , вам просто потрібно зареєструвати ваш картограф у файлі mapreduce.yaml та визначити функцію на зразок цієї:

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

На Java ви повинні ознайомитися з цією статтею, яка пропонує таку функцію:

@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:
Оскільки SDK 1.3.8, для цього є функція адміністратора Datastore


27

Ви можете очистити сховище даних сервера розробки під час запуску сервера:

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

Ви також можете скоротити --clear_datastoreдо -c.


5
Не впевнений, чи це нещодавня річ, але власне синтаксис зараз /path/to/google_appengine/dev_appserver.py --clear_datastore yes myappname/(зверніть увагу на "так")
Melllvar

Це найкорисніший спосіб багаторазового видалення сховища даних під час розробки. Якщо опції швидко застарівають, варто підкреслити, що цей прапор все ще діє в липні 2018 року, і він працює для dev_appserver, встановленого через gcloud CLI
Майкл

У версії 270.0.0 Google Cloud SDK "--clear_datastore = так" все ще працює зі знаком рівності
франки

15

Якщо у вас є значна кількість даних, для їх видалення потрібно використовувати скрипт. Однак ви можете використовувати remote_api для очищення сховища даних з боку клієнта прямо.


11

Ось ви перейдіть: Перейдіть до адміністратора зберігання даних, а потім виберіть тип сутності, який потрібно видалити, та натисніть кнопку Видалити. Mapreduce подбає про видалення!


9

Існує кілька способів видалення записів із сховища даних App Engine:

введіть тут опис зображення

  1. Спочатку подумайте, чи дійсно потрібно видаляти записи. Це дорого і може бути дешевше їх не видаляти.

  2. Ви можете видалити всі записи вручну за допомогою адміністратора Datastore.

  3. Ви можете використовувати віддалений API та інтерактивно видаляти записи.

  4. Ви можете видалити записи програмно, використовуючи пару рядків коду.

  5. Ви можете їх видалити масово, використовуючи черги завдань та курсори.

  6. Або ви можете скористатися Mapreduce, щоб отримати щось більш надійне і вигадливіше.

Кожен з цих методів пояснюється у наступному дописі в блозі: http://www.shiftedup.com/2015/03/28/how-to-bulk-delete-entries-in-app-engine-datastore

Сподіваюся, це допомагає!


6

Нульовий спосіб цього зробити - це надіслати HTTP-запит виконуваного довільного коду службі адміністратора, що ваш запущений додаток вже автоматично:

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

Це працює лише для сервера розробки. Чи є еквівалент виробництва?
Гаді

3

Джерело

Я отримав це від http://code.google.com/appengine/articles/remote_api.html .

Створіть інтерактивну консоль

Спочатку потрібно визначити інтерактивну консоль appenginge. Отже, створіть файл під назвою appengine_console.py і введіть це:

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



Створіть базовий клас Mapper

Як тільки це станеться, створіть цей клас Mapper. Я щойно створив новий файл під назвою utils.py і кинув це:

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 повинен бути просто абстрактним класом, який дозволяє переглядати кожну сутність певного виду, будь то витяг їх даних або їх модифікація та зберігання оновлених об'єктів назад у сховище даних.

Біжи з ним!

Тепер запустіть інтерактивну консоль appengine:

$python appengine_console.py <app_id_here>

Це має запустити інтерактивну консоль. У ньому створіть підклас моделі:

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

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

І, нарешті, запустіть його (від вашої інтерактивної консолі): mapper = MyModelDeleter () mapper.run ()

Це воно!


3

Це можна зробити за допомогою веб-інтерфейсу. Увійдіть у свій обліковий запис, перейдіть за посиланнями зліва. В управлінні магазином даних у вас є можливості змінити та видалити дані. Використовуйте відповідні параметри.


3

Я створив панель додатків, яку можна використовувати з розгорнутими додатками App Engine. У ньому перераховані види, які є у сховищі даних у спадному меню, і ви можете натиснути кнопку, щоб запланувати "завдання", які видаляють всі сутності певного виду або просто все. Завантажити його можна тут:
http://code.google.com/p/jobfeed/wiki/Nuke


3

Для Python 1.3.8 включає експериментальний вбудований для цього адміністратор. Вони кажуть : "увімкніть наступний вбудований файл у вашому файлі app.yaml:"

builtins:
- datastore_admin: on

"Видалення Datastore наразі доступне лише під час виконання Python. Програми Java, однак, все ще можуть скористатися цією функцією, створивши версію додатка Python, що не використовується за замовчуванням, яка дозволяє Datastore Admin в app.yaml. Вбудована підтримка Java. у майбутньому випуску ».


Додавання конфігурації в app.yaml призвело до помилки. Натомість ми можемо ввімкнути це на сторінці "Налаштування програм" у розділі "Адміністрація". Є кнопка, щоб це ввімкнути
Sundeep

3

Відкрийте "Адміністратор сховища даних" для своєї програми та ввімкніть Адміністратор. Тоді всі ваші особи будуть зазначені у вікнах. Ви можете просто вибрати небажані елементи та видалити їх.


3

Це те, що ви шукаєте ...

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

Запуск запиту лише для ключів набагато швидше, ніж повний збір, і ваша квота спричинить менший показник, оскільки запити, що стосуються лише ключів, вважаються невеликими операційними можливостями.

Ось посилання на відповідь Ніка Джонсона, що описує його далі.

Нижче представлено комплексне рішення REST API для обрізання таблиці ...

Я встановлюю API REST для обробки транзакцій бази даних, де маршрути безпосередньо відображаються у відповідну модель / дію. Це можна назвати, ввівши правильний URL (example.com/inventory/truncate) та увійшовши.

Ось маршрут:

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

Ось обробник:

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

Він починається з динамічного завантаження моделі (тобто Інвентар, знайдений під api.models), потім викликає правильний метод (Inventory.truncate ()), як зазначено в параметрі дії.

@Basic_auth - це декоратор / обгортка, що забезпечує аутентифікацію для чутливих операцій (тобто POST / DELETE). Також доступний декоратор oAuth, якщо ви стурбовані безпекою.

Нарешті, дія називається:

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

Це схоже на магію, але насправді це дуже просто. Найкраще, delete () можна повторно використовувати для обробки видалення одного або багатьох результатів, додавши в модель ще одну дію.


3

Ви можете видалити всі сховища даних, видаливши всі види один за одним. за допомогою панелі інструментів google appengine. Будь ласка, виконайте ці кроки.

  1. Увійдіть на сторінку https://console.cloud.google.com/datastore/settings
  2. Клацніть Відкрити адміністратор сховища даних . (Увімкніть його, якщо не ввімкнено.)
  3. Виберіть усі об'єкти та натисніть видалити. (На цьому кроці запустіть карту зменшити завдання для видалення всіх вибраних видів.)

Для отримання додаткової інформації див. це зображення http://storage.googleapis.com/bnifsc/Screenshot%20from%202015-01-31%2023%3A58%3A41.png


2

Якщо у вас багато даних, використання веб-інтерфейсу може зайняти багато часу. App Engine Launcher утиліта дозволяє видаляти всі в одному диханні з «Clear датастором на старті» прапорець. Ця утиліта тепер доступна як для Windows, так і для Mac (фреймворк Python).


2

Для сервера розробки замість запуску сервера через пусковий механізм програми Google можна запустити його з терміналу, наприклад:

dev_appserver.py --port = [portnumber] --clear_datastore = так [nameofapplication]

Наприклад: мій додаток "читач" працює на порту 15080. Після зміни коду та перезапуску сервера я просто запускаю "dev_appserver.py --port = 15080 --clear_datastore = yes reader".

Це добре для мене.


2

Додавання відповіді про останні події.

Нещодавно Google додав функцію адміністратора магазину даних. Ви можете створити резервну копію, видалити або скопіювати свої об'єкти в інший додаток за допомогою цієї консолі.

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


1

Я часто не хочу видаляти всі сховища даних, тому я витягаю чисту копію /war/WEB-INF/local_db.bin з керування джерелом. Це може бути я, але, здається, навіть із припиненим режимом Dev я повинен фізично видалити файл, перш ніж витягнути його. Це в Windows, використовуючи плагін для підриву для Eclipse.


0

Варіація 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);
        }
    }
}

Так, це займе час і 30 сек. є межа. Я думаю поставити зразок програми Ajax для автоматизації понад 30 сек.


Це навіть не дійсний php. import? Визначення константи як екземпляра об'єкта?
Джош 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

Якщо ви використовуєте ndb, метод, який працював на мене для очищення сховища даних:

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

1
Я не думаю, що це спрацює. Appengine скаржиться на Sorry, unexpected error: The kind "__Stat_Kind__" is reserved.це схоже на те, що у аппенгіну є якась внутрішня статистика, яку можна виявити за допомогою цього методу (можлива помилка на їх кінці?)
зник

0

Для будь-якого сховища даних, що знаходиться в двигуні додатків, а не локальному, ви можете використовувати новий API Datastore . Ось буквар, як розпочати роботу .

Я написав сценарій, який видаляє всі невбудовані сутності. API змінюється досить швидко, тому для довідки я клонував його на команду 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
  • продовжуючи ідею svpino, розумно повторно використовувати записи, позначені як видалити. (його ідея полягала не в тому, щоб видаляти, а позначати як "видалені" невикористані записи). трохи кеш-пам'яті / кеш-пам’яті для обробки робочої копії та запису в сховище даних лише різницю станів (до та після потрібного завдання), це покращить її. для великих завдань можна записати останні кінці різниці в сховище даних, щоб уникнути втрати даних, якщо пам’ять зникла. щоб зробити його стійким до втрат, можна перевірити цілісність / наявність запам’ятованих результатів і перезапустити завдання (або необхідну частину) для повторення відсутніх обчислень. коли різниця даних записується в сховище даних, необхідні обчислення відкидаються у чергу.

  • Інша ідея, схожа на карту, зменшена, - це розподілити вид сутності на кілька різних типів сутності, тому він буде зібраний разом і видно кінцевому користувачеві як єдиний вид сутності. записи позначаються лише як "видалені". коли кількість "видалених" записів на осколок долає деякий ліміт, "живі" записи розподіляються між іншими фрагментами, і цей осколок закривається назавжди, а потім видаляється вручну з консолі розробника (вгадайте, за меншими витратами) upd: здається, що на консолі немає таблиці, що випадає, видаляти тільки запис за записом за звичайною ціною.

  • можна видалити за допомогою запиту кухами великий набір записів без відмови від gae (принаймні, працює локально) з можливістю продовження в наступній спробі, коли час закінчиться:


    qdelete.getFetchPlan().setFetchSize(100);

    while (true)
    {
        long result = qdelete.deletePersistentAll(candidates);
        LOG.log(Level.INFO, String.format("deleted: %d", result));
        if (result <= 0)
            break;
    }
  • також іноді корисно робити додаткове поле в основній таблиці замість того, щоб поміщати кандидатів (пов'язані записи) в окрему таблицю. і так, поле може бути недекларованим / серіалізованим масивом з невеликими витратами на обчислення.

0

Для всіх людей, які потребують швидкого рішення для сервера розробників (як час написання в лютому 2016 року):

  1. Зупиніть сервер розробки.
  2. Видаліть цільовий каталог.
  3. Побудуйте проект.

Це видалить усі дані з сховища даних.


0

Мене так розчарували існуючі рішення для видалення всіх даних у магазині даних, що я жив, що я створив невеликий додаток GAE, який може видалити досить багато даних протягом 30 секунд.

Як встановити тощо: https://github.com/xamde/xydra


0

Для яви

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

Добре працює в сервері розвитку


0

У вас є два простих способи,

№1: Щоб заощадити витрати, видаліть весь проект

№2: використання ts-datastore-orm:

https://www.npmjs.com/package/ts-datastore-orm очікують Entity.truncate (); Урізання може видаляти близько 1 К рядків за секунду

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.