¿Eliminar publicaciones eliminadas permanentemente en bloque?

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

1 me gusta

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.

2 Me gusta

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

image

This might be the cause that your db still contains orphaned posts.

2 Me gusta

Creo que estás viendo que Data Explorer convierte automáticamente el entero en una URL, lo cual hace cuando la etiqueta es topic_id.

Cuando ejecuto esta consulta en Data Explorer, se capturan todas las publicaciones que intento identificar (bastante más de 5000):

SELECT id, topic_id
FROM posts
WHERE topic_id not in (select id from topics)
ORDER by id

Claramente estoy haciendo algo mal con mi sintaxis de Rails, ya que esto es lo que estoy obteniendo:

[1] pry(main)> Target = Post.where('topic_id not in (select id from topics)')
=> []

¿Alguien puede decirme qué estoy haciendo mal?

1 me gusta

Bueno, gracias a @pfaffman he identificado las publicaciones relevantes usando esto:

Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")

Obtengo esta salida:

[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.

Sin embargo, no puedo averiguar cómo aplicar destroy_all a esta selección.

Esto podría ayudar (para mi propio beneficio):

¿Alguna sugerencia?

1 me gusta

Creo que esto lo hará

posts=
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")


posts.destroy_all

O podrías añadir .destroy_all a tu find_by_sql

2 Me gusta

Lo he intentado. Los datos parecen devolverse como una matriz con algún identificador de publicación y un ID (ver Delete deleted-posts permanently in bulk? - #45 by nathank).

Este es el error que obtengo cuando añado .destroy_all o uso el posts= que sugieres:

[2] pry(main)> posts.destroy_all
NoMethodError: undefined method destroy_all' for #<Array:0x000055fe7bc7fc98> from (pry):3:in pry

1 me gusta

Oh. Entonces, quizás comprueba si

 p=posts.first

Es un post_id. Si es así, entonces puedes

x=Post.find(p)
x.destroy

Luego podrías iterar sobre ellos.

Creo que necesitarías envolver tu consulta en algo para que sea una matriz de posts en lugar de post_ids.

1 me gusta

Gracias Jay. Esto es lo que obtengo:

[3] pry(main)> p=
[3] pry(main)* posts.first
=> #<Post:0x0000563a24cab908 id: 150>
[4] pry(main)> x=Post.find(p)
ArgumentError: Estás pasando una instancia de ActiveRecord::Base a find. Por favor, pasa el id del objeto llamando a .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’

Ahora, háblame de estas cosas de envolver. Esto es tan molesto, porque sé que el comando de Rails de @Sam aquí debería funcionar, pero creo que Rails ha cambiado desde entonces:

1 me gusta

¿Qué hizo eso? No me imagino que los raíles cambiaran.

1 me gusta

¿Eso te da las publicaciones que quieres destruir?

1 me gusta

Leí en alguna parte en línea cuando buscaba cómo convertir un Array de Active Record en una Relación de Active Record que las cosas cambiaron entre Rails 3.x y Rails 4 y la sintaxis necesita ser diferente, pero no lo entendí muy bien.

Eso pareció recoger algunas cuando lo ejecuté por primera vez, y las destroy_all debidamente. Pero no había muchas. Ahora no recoge ninguna, mientras que el SQL recoge miles cuando se ejecuta en el Explorador de Datos.

Estas son Publicaciones huérfanas, donde el Tema ha sido Destroy_all’d.

1 me gusta

¿Puedes usar each{} para iterar los miembros de esa matriz, llamando a destroy en cada publicación individualmente?

Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy }
2 Me gusta

Bueno, lo he intentado. Primero no le gustó el SQL envuelto de esa manera ni la sintaxis:

Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy_all }
SyntaxError: unexpected `in’, expecting ‘(’
…rom posts where topic_id not in (select id from topics)”)…
… ^~
SyntaxError: unexpected local variable or method, expecting end-of-input
…t in (select id from topics)”).each { |p| p.destroy_all }

Así que le di otro intento improvisado dividiéndolo:

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

Esto pareció funcionar bien, pero al agregar p.destroy surge esto:

ActiveModel::MissingAttributeError: missing attribute: 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’

Intenté algunas formas de incluir eso, pero luego me rendí. @sam, ¿puedes ayudar?

P.S.

Incluso intenté convertir el SQL a AR a través de scuttle.io como se indica aquí:

Post.select([:id, :topic_id]).where(Topic.select(:id))

Por desgracia, obtengo este error:

ArgumentError: Unsupported argument type: #Topic::ActiveRecord_Relation:0x000055c67a7131d0 (Topic::ActiveRecord_Relation)

3 Me gusta

Cuando copié y pegué esa parte de un mensaje anterior, parece que las comillas se convirtieron en comillas rizadas en algún lugar, supongo que ese es el error real. Lo siento.

Se describe find_by_sql como que devuelve un objeto con los valores especificados en la consulta SQL, lo que presumiblemente significa que obtienes un objeto Post que solo tiene la propiedad id establecida, user_id y todo lo demás falta.

... find_by_sql("select * ... se encargará de eso. Probablemente haya un subconjunto de valores que podrías seleccionar para lograr un destroy, en lugar de seleccionar todo, pero no sé cuál sería ese subconjunto.

Así que todo el asunto: (esta vez sin comillas rizadas…)

Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }
4 Me gusta

:partying_face: ¡¡¡Aleluya!!! :partying_face:

Gracias Simon, funcionó de maravilla. Las publicaciones huérfanas han desaparecido y espero que mis cargas se reduzcan a casi nada en las próximas 24 horas.

más tarde
¡Y lo hicieron! De 3,5 GB a 0,7 GB. ¡Genial!

7 Me gusta

Excelente, me alegra saber que eso te funcionó. Así que, para combinar las respuestas, se puede usar lo siguiente en la consola de Rails para destruir todos los temas que fueron eliminados hace más de 90 días, repitiendo tantas veces como sea necesario si hay más de 1000 temas:

Topic.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all

Una vez que eso se complete, se puede usar lo siguiente para destruir todas las publicaciones que han quedado huérfanas de temas destruidos:

Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }

Vale la pena señalar que los comandos anteriores no destruirán las publicaciones eliminadas, solo los temas eliminados y sus publicaciones huérfanas. Para destruir también las publicaciones eliminadas de más de 90 días, usa lo siguiente, repitiendo nuevamente según sea necesario:

Post.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all

P.D. Por curiosidad, ¿probaste destroy_all sin limit(1000) y tuviste problemas o no lo intentaste sin el límite?

8 Me gusta

Lo intenté sin el límite y algo se volvió un poco loco, pero olvidé los detalles, lo siento.

¿Podemos marcar tu publicación como una solución o usar esto del OP?

image

3 Me gusta

No te preocupes. Si no lo hubieras intentado, habría añadido una nota de que el límite podría no ser necesario, pero como tuviste problemas, puedo dejarlo como está.

1 me gusta

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.