Seite 1 von 1
Django ORM: Lösche alle Einträge aber behalte die neusten X
Verfasst: Donnerstag 26. November 2009, 11:33
von jens
Ich möchte alle Einträge bis auf die neusten 10 löschen.
Anscheinend ist das ein wenig kompliziert. Meine momentane Lösung erscheint mir zu umständlich:
Code: Alles auswählen
number = 10
queryset = LogEntry.objects.all().order_by('-createtime')
ids = tuple(queryset[number:].values_list('id', flat=True))
queryset.filter(id__in=ids).delete()
tuple() in Zeile 6 ist bei MySQL erforderlich, damit wirklich zwei Queries ausgeführt werden. Ansonsten gibt es den Fehler:
This version of MySQL doesn't yet support 'LIMIT & IN/ALL/ANY/SOME subquery'
Einfacher wäre ja:
Code: Alles auswählen
number = 10
queryset = LogEntry.objects_site.all().order_by('-createtime')
queryset = queryset[-number:]
queryset.delete()
Geht aber nicht, es kommt der django Fehler:
Cannot use 'limit' or 'offset' with delete.
Verfasst: Freitag 27. November 2009, 08:21
von jens
Niemand eine bessere Lösung dafür?
Verfasst: Freitag 27. November 2009, 08:53
von frabron
Ich kenne mich jetzt nicht mit Djangos ORM aus, aber in SQL würde man doch einfach die Bedingung
Code: Alles auswählen
delete from dings where datecol < kleinstes_datum_zu_behaltendes_datum
formulieren. Das sollte doch aus in Django gehen, oder?
Verfasst: Freitag 27. November 2009, 09:08
von jens
Klar mit einem datum zu arbeiten ist weniger das Problem. Das kann so aussehen:
Code: Alles auswählen
datetime_filter = datetime.now() - timedelta(hours=2)
queryset = LogEntry.objects.all().order_by('-createtime')
queryset.exclude(createtime__gte=datetime_filter).delete()
Ich möchte es aber auch über die Anzahl machen: Behalte die neusten 10 Stück.
Verfasst: Freitag 27. November 2009, 09:51
von frabron
Und als Subselect?
Code: Alles auswählen
delete from foo where date < (select min(date) from foo order by date desc limit 10)
Re: Django ORM: Lösche alle Einträge aber behalte die neuste
Verfasst: Montag 2. Januar 2012, 17:24
von jens
Gerade nochmal mit "Cannot use 'limit' or 'offset' with delete." in den selben Fehler gelaufen
Also in SQL sollte das gehen:
Warum das mit dem Django ORM nicht geht, weiß ich nicht. Meine Momentane Lösung ist noch immer die von oben...
Re: Django ORM: Lösche alle Einträge aber behalte die neuste
Verfasst: Montag 2. Januar 2012, 19:58
von BlackJack
@jens: Bei so etwas muss man aber immer aufpassen worauf sich das LIMIT bezieht. Wenn man Pech hat nicht auf die sortierten Daten. Dann bekommt man 1000 „zufällige“ Datensätze die sinnloserweise vor dem Löschen halt noch sortiert werden.

Re: Django ORM: Lösche alle Einträge aber behalte die neuste
Verfasst: Dienstag 3. Januar 2012, 08:35
von jens
Das wäre natürlich fatal.
Im IRC wurde ich darauf hingewiesen, das anscheinend nicht alle DBs sowas können. MySQL kann es aber offensichtlich. Zumindest nach diesen Bug Einträgen zu Urteilen:
http://bugs.mysql.com/bug.php?id=1024
http://bugs.mysql.com/bug.php?id=12915
Wäre vielleicht mal eine Gelegenheit ein RAW-SQL zu erstellen. Aber ich vermute das sich der Aufwand in meinem Fall nicht lohnen wird. Denn in diesem Fall müßten immer nur wenige Einträge gelöscht werden. Wenn es aber wirklich viele sind, macht es wohl Sinn, denke ich...
Re: Django ORM: Lösche alle Einträge aber behalte die neuste
Verfasst: Dienstag 3. Januar 2012, 09:19
von /me
jens hat geschrieben:Code: Alles auswählen
number = 10
queryset = LogEntry.objects.all().order_by('-createtime')
ids = tuple(queryset[number:].values_list('id', flat=True))
queryset.filter(id__in=ids).delete()
Als kleine Optimierungsmöglichkeit - je nach Menge der Daten - könntest du auch aus dem Queryset die IDs holen die bleiben sollen und dann mit NOT IN löschen. "NOT IN" muss mit dem ORM von Django als .exclude(id__in=...) formuliert werden.
Re: Django ORM: Lösche alle Einträge aber behalte die neuste
Verfasst: Dienstag 3. Januar 2012, 09:29
von jens
@/me: Stimmt. Allerdings ist es beim mir umgekehrt. Es bleiben mehr als gehen müssen
