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.
Eu acho que você está vendo o Explorador de Dados convertendo automaticamente o inteiro em URL, o que ele faz quando o rótulo é topic_id.
Quando executo esta consulta no Explorador de Dados, todos os posts que estou tentando identificar são capturados (bem mais de 5000):
SELECT id, topic_id
FROM posts
WHERE topic_id not in (select id from topics)
ORDER by id
Eu estou claramente fazendo algo errado com a minha sintaxe Rails, pois é isso que estou recebendo:
[1] pry(main)> Target = Post.where('topic_id not in (select id from topics)')
=> []
Alguém pode me dizer o que estou fazendo de errado?
Bem, graças ao @pfaffman, identifiquei as postagens relevantes usando isto:
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
Eu recebo esta saída:
[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.
No entanto, não consigo descobrir como aplicar destroy_all a esta seleção.
Isto pode ajudar (para meu próprio benefício):
Alguma sugestão?
Acho que isso vai resolver
posts=
Post.find_by_sql("select id from posts where topic_id not in (select id from topics)")
posts.destroy_all
Ou você poderia adicionar o .destroy_all ao seu find_by_sql
Já tentei isso. Os dados parecem ser retornados como um array com algum identificador de postagem e um ID (veja Delete deleted-posts permanently in bulk? - #45 by nathank).
Este é o erro que recebo quando adiciono .destroy_all ou uso o posts= que você sugere:
[2] pry(main)> posts.destroy_all
NoMethodError: undefined methoddestroy_all' for #<Array:0x000055fe7bc7fc98> from (pry):3:inpry’
Oh. Então talvez veja se
p=posts.first
É um post_id. Se for isso, então você pode
x=Post.find(p)
x.destroy
Então você poderia percorrer esses.
Acho que você precisaria envolver sua consulta em algo para que ela se tornasse uma matriz de posts em vez de ids de posts.
Obrigado, Jay. É isto que recebo:
[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 tofind. 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’
Agora, fale-me sobre essas coisas de envolver. Isso é tão irritante, porque eu sei que o comando rails do @Sam aqui deveria funcionar, mas acho que o Rails mudou desde então:
O que isso fez? Não consigo imaginar que o Rails mudou.
Isso retorna os posts que você quer destruir?
Li em algum lugar online ao pesquisar sobre a conversão de um Active Record Array em um Active Record Relation que as coisas mudaram entre o Rails 3.x e o Rails 4 e a sintaxe precisa ser diferente, mas não entendi muito bem.
Isso pareceu capturar alguns quando executei pela primeira vez, e eu devidamente os destroy_all’ei. Mas não eram muitos. Agora não capta nenhum, enquanto o SQL capta milhares quando executado no Data Explorer.
Estes são Posts órfãos, onde o Tópico foi Destroy_all’ado.
Você pode usar each{} para iterar sobre os membros desse array, chamando destroy em cada post individualmente?
Post.find_by_sql(“select id from posts where topic_id not in (select id from topics)”).each { |p| p.destroy }
Bem, eu tentei. Primeiro, ele não gostou do SQL empacotado dessa forma nem da sintaxe:
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 ‘(’\n…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 }
Então, fiz outra tentativa improvisada, dividindo-a:
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
Isso pareceu funcionar bem, mas adicionar o p.destroy gera isso:
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’
Tentei algumas maneiras de incluir isso, mas depois desisti. @sam, você pode ajudar?
Eu até tentei converter o SQL para AR via scuttle.io, conforme isto:
Post.select([:id, :topic_id]).where(Topic.select(:id))
Infelizmente, recebo este erro:
ArgumentError: Unsupported argument type: #Topic::ActiveRecord_Relation:0x000055c67a7131d0 (Topic::ActiveRecord_Relation)
Quando copiei e colei essa parte de uma mensagem anterior, parece que as aspas foram convertidas em aspas curvas em algum lugar, imagino que esse seja o erro real. Desculpe por isso.
O find_by_sql é descrito como retornando um objeto com os valores especificados na consulta SQL, o que presumivelmente significa que você está recebendo um objeto Post que tem apenas a propriedade id definida, user_id e todo o resto está faltando.
... find_by_sql("select * ... lidará com isso. Provavelmente há um subconjunto de valores que você poderia selecionar para conseguir um destroy, em vez de selecionar tudo, mas não sei qual seria esse subconjunto.
Então, tudo isso: (sem aspas curvas desta vez…)
Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }
Obrigado Simon - funcionou maravilhosamente. As postagens órfãs desapareceram e espero que meus uploads diminuam para quase nada nas próximas 24 horas.
mais tarde
E diminuíram! 3,5 GB para 0,7 GB. Perfeito!!
Excelente, fico feliz em saber que isso resolveu o seu problema. Para fins de combinação das respostas, pode-se usar o seguinte no console do Rails para excluir todos os tópicos que foram excluídos há mais de 90 dias, repetindo quantas vezes forem necessárias se houver mais de 1000 tópicos:
Topic.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all
Após a conclusão disso, o seguinte pode ser usado para excluir todas as postagens órfãs de tópicos excluídos:
Post.find_by_sql("select * from posts where topic_id not in (select id from topics)").each { |p| p.destroy }
Vale notar que os comandos acima não excluirão postagens excluídas, apenas tópicos excluídos e suas postagens órfãs. Para também excluir postagens excluídas com mais de 90 dias, use o seguinte, novamente repetindo conforme necessário:
Post.with_deleted.where(deleted_at: ...90.days.ago).limit(1000).destroy_all
P.S. Por curiosidade, você tentou destroy_all sem limit(1000) e teve problemas ou não tentou sem o limite?
Eu tentei sem o limite e algo ficou um pouco louco - mas esqueço os detalhes, desculpe.
Podemos marcar sua postagem como uma solução ou usar esta do OP?

Sem problemas. Se você não tivesse tentado, eu teria adicionado uma nota de que o limite pode não ser necessário, mas como você teve problemas, posso deixá-lo como está.
This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.