Удалите все данные для вида в Google App Engine

45
задан user8548 20 September 2008 в 17:34
поделиться

11 ответов

официальный ответ от Google - то, что необходимо удалить в блоках, распространенных по нескольким запросам. Можно использовать Ajax, обновление meta , или запросить URL из сценария, пока нет никаких оставленных объектов.

6
ответ дан Alexander Kojevnikov 8 November 2019 в 00:53
поделиться

Я попробовал db.delete (результаты) и Консоль Механизма Приложения, и ни один из них, кажется, не работает на меня. Вручную удаляющие записи от Средства просмотра Данных (увеличенный предел до 200) не работали ни один, так как я загрузил больше чем 10 000 записей. Я закончил запись этого сценария

from google.appengine.ext import db
from google.appengine.ext import webapp
from google.appengine.ext.webapp.util import run_wsgi_app
import wsgiref.handlers
from mainPage import YourData #replace this with your data
class CleanTable(webapp.RequestHandler):
    def get(self, param):
        txt = self.request.get('table')
        q = db.GqlQuery("SELECT * FROM "+txt)
        results = q.fetch(10)
        self.response.headers['Content-Type'] = 'text/plain'
        #replace yourapp and YouData your app info below.
        self.response.out.write("""
          <html>
          <meta HTTP-EQUIV="REFRESH" content="5; url=http://yourapp.appspot.com/cleanTable?table=YourData">
            <body>""")

        try:
            for i in range(10):
                db.delete(results)
                results = q.fetch(10, len(results))
                self.response.out.write("<p>10 removed</p>")
                self.response.out.write("""
                </body>
              </html>""")

        except Exception, ints:
            self.response.out.write(str(inst))

def main():
  application = webapp.WSGIApplication([
    ('/cleanTable(.*)', CleanTable),
  ])

  wsgiref.handlers.CGIHandler().run(application)  

, прием должен был включать перенаправление в HTML вместо того, чтобы использовать self.redirect. Я готов ожидать в течение ночи для избавлений от всех данных в моей таблице. Хотелось бы надеяться, команда GAE облегчит отбрасывать таблицы в будущем.

7
ответ дан 8 November 2019 в 00:53
поделиться

Попытайтесь использовать Консоль Механизма Приложения тогда, Вы не должны даже развертывать специальный код

9
ответ дан Sam 8 November 2019 в 00:53
поделиться

К сожалению, нет никакого способа легко сделать, объем удаляет. Ваш лучший выбор состоит в том, чтобы записать сценарий, который удаляет разумное количество записей на вызов, и затем звоните, это неоднократно - например, при наличии Вашего удалять сценарий возвращает 302 перенаправления каждый раз, когда существует больше данных для удаления, затем выбирая его с "wget - max-redirect=10000" (или некоторое другое большое количество).

3
ответ дан Nick Johnson 8 November 2019 в 00:53
поделиться

По-видимому, Ваш взлом был чем-то вроде этого:

# Deleting all messages older than "earliest_date"
q = db.GqlQuery("SELECT * FROM Message WHERE create_date < :1", earliest_date)
results = q.fetch(1000)

while results:
    db.delete(results)
    results = q.fetch(1000, len(results))

, Как Вы говорите, если существуют достаточные данные, Вы собираетесь поразить тайм-аут запроса, прежде чем это пройдет через все записи. Необходимо было бы повторно вызвать этот запрос многократно снаружи, чтобы гарантировать, что все данные были стерты; достаточно легкий сделать, но едва идеальный.

консоль администрирования, кажется, не предлагает справки, как (на основе моего собственного опыта с ним), это, кажется, только позволяет объектам данного типа быть перечисленными и затем удаленными на постранично основание.

При тестировании, я должен был произвести чистку своей базы данных по запуску для избавлений от существующих данных.

я вывел бы из этого, что Google воздействует на принцип, что диск является дешевым, и таким образом, данные являются обычно осиротевшими (индексы к избыточным замененным данным), а не удаленный. Данный существует установленная сумма доступных данных к каждому приложению в данный момент (0,5 ГБ), это не много справки для пользователей не-Google App Engine.

9
ответ дан Riccardo 8 November 2019 в 00:53
поделиться

В настоящее время я удаляю объекты по их ключу, и это кажется быстрее.

from google.appengine.ext import db

class bulkdelete(webapp.RequestHandler):
    def get(self):
        self.response.headers['Content-Type'] = 'text/plain'
        try:
            while True:
                q = db.GqlQuery("SELECT __key__ FROM MyModel")
                assert q.count()
                db.delete(q.fetch(200))
                time.sleep(0.5)
        except Exception, e:
            self.response.out.write(repr(e)+'\n')
            pass

с терминала я запускаю curl -N http: // ...

28
ответ дан 26 November 2019 в 21:04
поделиться

Одна подсказка. Я предлагаю вам ознакомиться с remote_api для этих типов использования (массовое удаление, изменение и т. Д.). Но даже при использовании удаленного API размер пакета может быть ограничен несколькими сотнями за раз.

4
ответ дан 26 November 2019 в 21:04
поделиться

Если бы я был параноиком, я бы сказал, что Google App Engine (GAE) не упростил нам удаление данных, если мы этого хотим. Я пропущу обсуждение размеров индексов и того, как они преобразуют 6 ГБ данных в 35 ГБ хранилища (за которые взимается плата). Это другая история, но у них есть способы обойти это - ограничить количество свойств для создания индекса (автоматически сгенерированные индексы) и так далее.

Я решил написать этот пост, потому что мне нужно «уничтожить» все Виды мои в песочнице. Я читал об этом и, наконец, придумал этот код:

package com.intillium.formshnuker;

import java.io.IOException;
import java.util.ArrayList;

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import com.google.appengine.api.datastore.Key;
import com.google.appengine.api.datastore.Query;
import com.google.appengine.api.datastore.Entity;
import com.google.appengine.api.datastore.FetchOptions;
import com.google.appengine.api.datastore.DatastoreService;
import com.google.appengine.api.datastore.DatastoreServiceFactory;

import com.google.appengine.api.labs.taskqueue.QueueFactory;
import com.google.appengine.api.labs.taskqueue.TaskOptions.Method;

import static com.google.appengine.api.labs.taskqueue.TaskOptions.Builder.url;

@SuppressWarnings("serial")
public class FormsnukerServlet extends HttpServlet {

 public void doGet(final HttpServletRequest request, final HttpServletResponse response) throws IOException {

  response.setContentType("text/plain");

  final String kind = request.getParameter("kind");
  final String passcode = request.getParameter("passcode");

  if (kind == null) {
   throw new NullPointerException();
  }

  if (passcode == null) {
   throw new NullPointerException();
  }

  if (!passcode.equals("LONGSECRETCODE")) {
   response.getWriter().println("BAD PASSCODE!");
   return;
  }

  System.err.println("*** deleting entities form " + kind);

  final long start = System.currentTimeMillis();

  int deleted_count = 0;
  boolean is_finished = false;

  final DatastoreService dss = DatastoreServiceFactory.getDatastoreService();

  while (System.currentTimeMillis() - start < 16384) {

   final Query query = new Query(kind);

   query.setKeysOnly();

   final ArrayList<Key> keys = new ArrayList<Key>();

   for (final Entity entity: dss.prepare(query).asIterable(FetchOptions.Builder.withLimit(128))) {
    keys.add(entity.getKey());
   }

   keys.trimToSize();

   if (keys.size() == 0) {
    is_finished = true;
    break;
   }

   while (System.currentTimeMillis() - start < 16384) {

    try {

     dss.delete(keys);

     deleted_count += keys.size();

     break;

    } catch (Throwable ignore) {

     continue;

    }

   }

  }

  System.err.println("*** deleted " + deleted_count + " entities form " + kind);

  if (is_finished) {

   System.err.println("*** deletion job for " + kind + " is completed.");

  } else {

   final int taskcount;

   final String tcs = request.getParameter("taskcount");

   if (tcs == null) {
    taskcount = 0;
   } else {
    taskcount = Integer.parseInt(tcs) + 1;
   }

   QueueFactory.getDefaultQueue().add(
    url("/formsnuker?kind=" + kind + "&passcode=LONGSECRETCODE&taskcount=" + taskcount).method(Method.GET));

   System.err.println("*** deletion task # " + taskcount + " for " + kind + " is queued.");

  }

  response.getWriter().println("OK");

 }

}

У меня более 6 миллионов записей. Это много. Я понятия не имею, сколько будет стоить удаление записей (может быть, более экономично не удалять их). Другой альтернативой может быть запрос на удаление всего приложения (песочницы). Но это' в большинстве случаев это нереально.

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

Мой запрос от команды GAE: добавьте функцию для удаления всех объектов одного типа за одну транзакцию.

10
ответ дан 26 November 2019 в 21:04
поделиться

Вы можете использовать очереди задач для удаления фрагментов, скажем, из 100 объектов. Удаление объектов в GAE показывает, насколько ограничены возможности администратора в GAE . Вы должны работать с пакетами по 1000 или меньше объектов. Вы можете использовать инструмент массовой загрузки, который работает с CSV, но документация не охватывает java. Я использую GAE Java, и моя стратегия удаления включает в себя наличие двух сервлетов, один для фактического удаления, а другой для загрузки задачи очереди. Когда я хочу выполнить удаление, я запускаю сервлет загрузки очереди, он загружает очереди, а затем GAE приступает к работе, выполняя все задачи в очереди.

Как это сделать: Создайте сервлет, который удаляет небольшое количество объектов. Добавьте сервлет в очереди задач. Идите домой или поработайте над чем-нибудь другим; ) Проверяйте хранилище данных так часто ...

У меня есть хранилище данных с примерно 5000 объектами, которые я очищаю каждую неделю, и на очистку уходит около 6 часов, поэтому я запускаю задачу в пятницу вечером. Я использую тот же метод для массовой загрузки моих данных, которые составляют около 5000 объектов с примерно дюжиной свойств.

0
ответ дан 26 November 2019 в 21:04
поделиться

С django, URL-адрес настройки:

url(r'^Model/bdelete/$', v.bulk_delete_models, {'model':'ModelKind'}),

Просмотр настроек

def bulk_delete_models(request, model):
    import time
    limit = request.GET['limit'] or 200
    start = time.clock()
    set = db.GqlQuery("SELECT __key__ FROM %s" % model).fetch(int(limit))
    count = len(set)
    db.delete(set)
    return HttpResponse("Deleted %s %s in %s" % (count,model,(time.clock() - start)))

Затем запустите в PowerShell:

$client = new-object System.Net.WebClient
$client.DownloadString("http://your-app.com/Model/bdelete/?limit=400")
1
ответ дан 26 November 2019 в 21:04
поделиться

У меня это сработало:

class ClearHandler(webapp.RequestHandler):  
    def get(self):  
        self.response.headers['Content-Type'] = 'text/plain'  
        q = db.GqlQuery("SELECT * FROM SomeModel")  
        self.response.out.write("deleting...")  
        db.delete(q)
0
ответ дан 26 November 2019 в 21:04
поделиться
Другие вопросы по тегам:

Похожие вопросы: