If I am not mistaken there is a field called deleted_at
If it is deleted, then there should be a date time Stamp.
If it is not deleted then is null
Maybe look for the entry that is <> Null and delete
If I am not mistaken there is a field called deleted_at
If it is deleted, then there should be a date time Stamp.
If it is not deleted then is null
Maybe look for the entry that is <> Null and delete
Thanks Gav, but the ones that I am targeting aren’t marked as deleted. Rather, their Topic has been deleted and then destroy_all’d.
I was playing around with this and i notice that part of your query was not returning the response you need.
SELECT topic_id from posts does not return an integer, but it returned a string

This might be the cause that your db still contains orphaned posts.
Ich glaube, dass Sie Data Explorer sehen, der die Ganzzahl automatisch in eine URL umwandelt, was er tut, wenn das Label topic_id ist.
Wenn ich diese Abfrage in Data Explorer ausführe, werden alle Beiträge, die ich zu identifizieren versuche, erfasst (weit über 5000):
SELECT id, topic_id
FROM posts
WHERE topic_id not in (select id from topics)
ORDER by id
Ich mache eindeutig etwas falsch mit meiner Rails-Syntax, da dies das ist, was ich bekomme:
[1] pry(main)> Target = Post.where('topic_id not in (select id from topics)')
=> []
Kann mir jemand sagen, was ich falsch mache?
Dank @pfaffman habe ich die relevanten Beiträge mit Folgendem identifiziert:
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
Ich erhalte diese Ausgabe:
[1] pry(main)> Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”)
=> [#<Post:0x000055df30d4ee90 id: 150>,
#<Post:0x000055df2e538ff0 id: 51097>,
#<Post:0x000055df2e50ba28 id: 83>,
#<Post:0x000055df2e4ee8b0 id: 40636>,
#<Post:0x000055df2e4a92d8 id: 62562>,
#<Post:0x000055df2e4b7978 id: 13522>,
etc.
Ich kann jedoch nicht herausfinden, wie ich destroy_all auf diese Auswahl anwenden kann.
Das könnte helfen (zu meinem eigenen Nutzen):
Irgendwelche Vorschläge?
Ich glaube, das wird es tun
posts=
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
posts.destroy_all
Oder Sie könnten .destroy_all zu Ihrem find_by_sql hinzufügen
Ich habe das versucht. Die Daten scheinen als Array mit einer Bezeichner-ID zurückgegeben zu werden (siehe Delete deleted-posts permanently in bulk? - #45 by nathank).
Dies ist der Fehler, den ich erhalte, wenn ich entweder .destroy_all hinzufüge oder das von Ihnen vorgeschlagene posts= verwende:
[2] pry(main)> posts.destroy_all
NoMethodError: undefined methoddestroy_all' for #<Array:0x000055fe7bc7fc98> from (pry):3:inpry’
Oh. Dann sehen Sie vielleicht nach, ob
p=posts.first
eine post_id ist. Wenn das alles ist, können Sie
x=Post.find(p)
x.destroy
Dann könnten Sie diese durchlaufen.
Ich denke, Sie müssten Ihre Abfrage in etwas einpacken, um sie zu einem Array von Posts und nicht zu Post-IDs zu machen.
Danke Jay. Das bekomme ich:
[3] pry(main)> p=
[3] pry(main)* posts.first
=> #<Post:0x0000563a24cab908 id: 150>
[4] pry(main)> x=Post.find(p)
ArgumentError: You are passing an instance of ActiveRecord::Base to find. Please pass the id of the object by calling .id.
from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activerecord-6.1.4.1/lib/active_record/relation/finder_methods.rb:467:in find_one’`
Erzähl mir jetzt von diesen Wrap-Dingen. Das ist so nervig, weil ich weiß, dass @Sams Rails-Befehl hier funktionieren sollte, aber ich denke, Rails hat sich seitdem geändert:
Was hat das bewirkt? Ich kann mir nicht vorstellen, dass sich Rails geändert hat.
Liefert das die Beiträge, die du löschen möchtest?
Ich habe irgendwo online gelesen, als ich nach der Konvertierung eines Active Record Arrays in eine Active Record Relation suchte, dass sich zwischen Rails 3.x und Rails 4 etwas geändert hat und die Syntax anders sein muss, aber es ging mir wirklich über den Kopf.
Das schien anfangs ein paar aufzunehmen, als ich es zum ersten Mal ausführte, und ich habe sie ordnungsgemäß mit destroy_all zerstört. Aber es waren nicht viele. Jetzt werden gar keine mehr aufgenommen, während die SQL-Abfrage im Data Explorer Tausende von Beiträgen findet.
Dies sind verwaiste Beiträge, bei denen das Thema mit Destroy_all zerstört wurde.
Können Sie each{} verwenden, um die Elemente dieses Arrays zu durchlaufen und destroy für jeden Beitrag einzeln aufzurufen?
Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy }
Nun, ich habe es versucht. Zuerst mochte es die SQL-Abfrage nicht, die so verpackt war, noch die Syntax:
Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy_all }
SyntaxError: unerwartetes `in’, erwartet ‘(’\n…rom posts where topic_id not in (select id from topics)”)…\n… ^~\nSyntaxError: unerwartete lokale Variable oder Methode, erwartet end-of-input\n…t in (select id from topics)”).each { |p| p.destroy_all }\n
Also habe ich es noch einmal auf eine andere, umständliche Weise versucht, indem ich es aufgeteilt habe:
posts=Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
posts.each do |p|
p.destroy
end
Das schien okay zu laufen, aber das Hinzufügen von p.destroy wirft dies auf:
ActiveModel::MissingAttributeError: fehlendes Attribut: user_id
from /var/www/discourse/vendor/bundle/ruby/2.7.0/gems/activemodel-6.1.4.1/lib/active_model/attribute.rb:222:in `value’
Ich habe ein paar Wege versucht, das da reinzubekommen, habe dann aber aufgegeben. @sam, kannst du helfen?
Ich habe sogar versucht, die SQL-Abfrage mit scuttle.io in AR zu konvertieren, wie hier beschrieben:
Post.select([:id, :topic_id]).where(Topic.select(:id))
Leider erhalte ich diesen Fehler:
ArgumentError: Nicht unterstützter Argumenttyp: #Topic::ActiveRecord_Relation:0x000055c67a7131d0 (Topic::ActiveRecord_Relation)
Als ich diesen Teil aus einer früheren Nachricht kopiert und eingefügt habe, scheinen die Anführungszeichen irgendwo in geschweifte Anführungszeichen umgewandelt worden zu sein. Ich vermute, das ist der eigentliche Fehler. Entschuldigung dafür.
find_by_sql gibt ein Objekt mit den in der SQL-Abfrage angegebenen Werten zurück, was vermutlich bedeutet, dass Sie ein Post-Objekt erhalten, bei dem nur die Eigenschaft id gesetzt ist und user_id und alles andere fehlt.
... find_by_sql("select * ... wird damit umgehen. Es gibt wahrscheinlich eine Teilmenge von Werten, die Sie auswählen könnten, um eine Zerstörung zu erreichen, anstatt alles auszuwählen, aber ich weiß nicht, wie diese Teilmenge aussehen würde.
Also das Ganze: (diesmal ohne geschweifte Anführungszeichen…)
Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }
Danke Simon – das hat wunderbar funktioniert. Die verwaisten Beiträge sind alle weg und ich freue mich darauf, dass meine Uploads in den nächsten 24 Stunden oder so auf fast nichts schrumpfen werden.
später
Und das taten sie! 3,5 GB auf 0,7 GB reduziert. Super!!
Ausgezeichnet, ich freue mich zu hören, dass das für Sie funktioniert hat. Um die Antworten zu kombinieren, können Sie Folgendes in der Rails-Konsole verwenden, um alle Themen zu löschen, die vor mehr als 90 Tagen gelöscht wurden. Wiederholen Sie dies so oft wie nötig, wenn mehr als 1000 Themen vorhanden sind:
Topic.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all
Nachdem dies abgeschlossen ist, können Sie Folgendes verwenden, um alle Beiträge zu löschen, die von gelöschten Themen verwaist sind:
Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }
Es ist erwähnenswert, dass die obigen Befehle keine gelöschten Beiträge zerstören, sondern nur gelöschte Themen und deren verwaiste Beiträge. Um auch gelöschte Beiträge zu zerstören, die älter als 90 Tage sind, verwenden Sie Folgendes, wiederholen Sie dies bei Bedarf:
Post.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all
PS Aus Interesse, haben Sie destroy_all ohne limit(1000) versucht und Probleme gehabt oder haben Sie es nicht ohne das Limit versucht?
Ich habe es ohne das Limit versucht und etwas ist ein wenig verrückt geworden – aber ich erinnere mich leider nicht mehr an die Details.
Können wir Ihren Beitrag als Lösung markieren oder diesen vom OP verwenden?

Kein Problem. Wenn Sie es nicht versucht hätten, hätte ich eine Notiz hinzugefügt, dass das Limit möglicherweise nicht notwendig ist, aber da Sie Probleme hatten, kann ich es einfach so belassen, wie es ist.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.