Как удалить все хранилища данных в Google App Engine?


122

Кто-нибудь знает, как удалить все хранилища данных в Google App Engine ?


2
db.delete (db.Query (keys_only = True)). Дополнительные сведения см. Здесь stackoverflow.com/a/10856555/290340 .
Evan Plaice

4
Как указано ниже в @systempuntoout, у GAE теперь есть администратор хранилища данных, который, помимо прочего, позволяет вам массово удалять объекты без какого-либо кодирования. Эту функцию нужно упомянуть здесь, а не закопать в третьем комментарии.
ralfoide

Администратор хранилища данных не работает (страница загружает iframe на несуществующий хост), поэтому нам все равно придется использовать метод db.delete.

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

Ответы:


69

Если вы говорите о живом хранилище данных , откройте панель управления вашего приложения (войдите в appengine), затем хранилище данных -> просмотрщик данных, выберите все строки для таблицы, которую вы хотите удалить, и нажмите кнопку удаления (вам придется сделайте это для всех ваших таблиц). Вы можете сделать то же самое программно через remote_api (но я никогда не использовал его).

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

Обязательно очистите свой проект после этого.

Это одна из маленьких ловушек, которые пригодятся, когда вы начнете играть с Google Application Engine. Вы обнаружите, что сохраняете объекты в хранилище данных, а затем изменяете объектную модель JDO для своих устойчивых сущностей, в результате чего получаются устаревшие данные, что приведет к сбою вашего приложения повсюду.


16
В dev_appserver.py есть параметр -c, который нужно удалить из хранилища данных разработки.
svrist

1
@svrist Но это относится только к движку приложений Python. Кто-нибудь знает, как сделать это на Java? (Между тем, предложение JohnIdol работает хорошо.)
mgiuca

2
Спасибо @John: Где точный путь в MAC OSX?
Джордж Нгуен

3
Где путь в винде?
Шейн Бест

2
@ShaneBest путь в окнах что - то вроде ./target/yourappid-1.0-SNAPSHOT/WEB-INF/appengine-generated/local_db.bin
Морфеус

58

Лучшим подходом является метод удаленного API, предложенный Ником, он инженер App Engine из Google , так что доверяйте ему.

Это не так уж и сложно, и последняя версия 1.2.5 SDK предоставляет remote_shell_api.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 01

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

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

Самый быстрый и эффективный способ справиться с навалом удалить на датастор с помощью нового сопоставителя API объявил на последней конференции Google I / O .

Если вы предпочитаете язык 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());
}

РЕДАКТИРОВАТЬ:
Начиная с SDK 1.3.8, для этой цели есть функция администратора хранилища данных.


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/(обратите внимание на «да»)
Меллвар

Это наиболее удобный способ многократного удаления хранилища данных во время разработки. Поскольку параметры быстро устаревают, стоит отметить, что этот флаг все еще действует в июле 2018 года и работает для dev_appserver, установленного через интерфейс командной строки gcloud
Майкл

В версии 270.0.0 Google Cloud SDK "--clear_datastore = yes" по-прежнему работает со знаком равенства
Фрэнксандс

15

Если у вас есть значительный объем данных, вам необходимо использовать сценарий для его удаления. Однако вы можете использовать remote_api, чтобы очистить хранилище данных со стороны клиента простым способом.


11

Вот и все: перейдите в Администратор хранилища данных, выберите тип объекта, который вы хотите удалить, и нажмите «Удалить». Mapreduce позаботится об удалении!


9

Удалить записи из хранилища данных App Engine можно несколькими способами:

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

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

  2. Вы можете удалить все записи вручную с помощью администратора хранилища данных.

  3. Вы можете использовать Remote 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())'}))

Это работает только для сервера разработки. Есть производственный эквивалент?
Gady

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

"Удаление хранилища данных в настоящее время доступно только в среде выполнения Python. Однако приложения Java могут по-прежнему использовать эту функцию, создав версию приложения Python, отличную от стандартной, которая включает администратор хранилища данных в app.yaml. Встроенная поддержка Java будет включена в следующем выпуске ".


Добавление конфигурации в app.yaml вызывало ошибку. Вместо этого мы можем включить его на странице «Настройки приложений» в разделе «Администрирование». Есть кнопка для включения
Sundeep

3

Откройте «Администратор хранилища данных» для своего приложения и включите Админ. После этого все ваши объекты будут отмечены флажками. Вы можете просто выбрать ненужные объекты и удалить их.


3

Это то, что вы ищете ...

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

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

Вот ссылка на ответ Ника Джонсона, который описывает это дальше.

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

Я настраиваю REST API для обработки транзакций базы данных, где маршруты напрямую сопоставляются с соответствующей моделью / действием. Это можно вызвать, введя правильный 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. Щелкните Открыть Datastore Admin . (Включите, если не включен.)
  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 = [номер порта] --clear_datastore = да [nameofapplication]

Пример: мое приложение «reader» работает на порту 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 из системы управления версиями. Возможно, это только я, но кажется, что даже с остановленным режимом разработки мне нужно физически удалить файл, прежде чем вытащить его. Это в Windows с использованием подключаемого модуля Subversion для 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? Определение константы как экземпляра объекта?
Джош Дж,

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.это похоже, что appengine имеет некую внутреннюю статистическую сущность, которая может быть обнаружена этим методом (возможная ошибка на их стороне?)
исчез

0

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

Я написал сценарий, который удаляет все не встроенные сущности. 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, разумно повторно использовать записи, помеченные как delete. (его идея заключалась не в том, чтобы удалить, а пометить как «удаленные» неиспользуемые записи). немного кеша / кеша памяти для обработки рабочей копии и записи только разницы состояний (до и после желаемой задачи) в хранилище данных сделает его лучше. для больших задач можно записывать в хранилище данных фрагменты промежуточных отличий, чтобы избежать потери данных в случае исчезновения кэша памяти. чтобы сделать его без потерь, можно проверить целостность / существование результатов memcached и перезапустить задачу (или требуемую часть), чтобы повторить недостающие вычисления. когда разница в данных записывается в хранилище данных, необходимые вычисления сбрасываются в очередь.

  • Другая идея, аналогичная уменьшенной карте, - это разделение типа сущности на несколько разных типов сущностей, поэтому они будут собраны вместе и видны конечному пользователю как единый вид сущности. записи помечаются только как «удаленные». когда количество "удаленных" записей на шард превышает некоторый предел, "живые" записи распределяются между другими шардами, и этот шард закрывается навсегда, а затем удаляется вручную из консоли разработчика (предположительно с меньшими затратами). 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

Для 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);

Хорошо работает в сервере разработки


Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.